diff --git a/__init__.py b/__init__.py index cbd7774..9efacbc 100644 --- a/__init__.py +++ b/__init__.py @@ -10,6 +10,7 @@ from .modules.pandas_wrapper.pandas_index import PandasIndex from .modules.pandas_wrapper.pandas_join import PandasJoin from .modules.pandas_wrapper.pandas_load_csv import PandasLoadCSV from .modules.pandas_wrapper.pandas_load_csv_with_index import PandasLoadCSVWithIndex +from .modules.pandas_wrapper.pandas_loc_cell_str import PandasLocCellStr from .modules.pandas_wrapper.pandas_save_csv import PandasSaveCSV from .modules.pandas_wrapper.pandas_select_columns import PandasSelectColumns from .modules.pandas_wrapper.pandas_select_rows import PandasSelectRows @@ -33,6 +34,7 @@ NODE_CLASS_MAPPINGS: Dict[str, Type[T]] = { "PandasJoin": PandasJoin, "PandasLoadCSV": PandasLoadCSV, "PandasLoadCSVWithIndex": PandasLoadCSVWithIndex, + "PandasLocCellStr": PandasLocCellStr, "PandasSaveCSV": PandasSaveCSV, "PandasSelectColumns": PandasSelectColumns, "PandasSelectRows": PandasSelectRows, @@ -59,6 +61,7 @@ NODE_DISPLAY_NAME_MAPPINGS: Dict[str, str] = { "PandasJoin": "Pandas Join", "PandasLoadCSV": "Pandas Load CSV", "PandasLoadCSVWithIndex": "Pandas Load CSV with Index", + "PandasLocCellStr": "Pandas Loc Cell Str", "PandasSaveCSV": "Pandas Save CSV", "PandasSelectColumns": "Pandas Select Columns", "PandasSelectRows": "Pandas Select Rows", diff --git a/docs/images/loc_cell_str.png b/docs/images/loc_cell_str.png new file mode 100644 index 0000000..02ed940 Binary files /dev/null and b/docs/images/loc_cell_str.png differ diff --git a/docs/ug.md b/docs/ug.md index 2a2efe7..b1b2000 100644 --- a/docs/ug.md +++ b/docs/ug.md @@ -22,6 +22,7 @@ You can right-click, select **Add Node**, go to **Data Analysis**, and look for | **Pandas Index** | Extract row labels (index) | | **Pandas Select Columns** | Select specific columns from a DataFrame | | **Pandas Select Rows** | Filter rows based on conditions | +| **Pandas Loc Cell Str** | Select a cell by row label (index) and column label (index) | | **Pandas Join** | Join two DataFrames | | **Pandas Head** | Extract the first few rows | | **Pandas Show DataFrame** | Display DataFrame contents | @@ -63,6 +64,13 @@ Use **Pandas Select Columns** for selecting columns, **Pandas Select Rows** to s ![Pandas select subset](images/subset.jpg) +## Selecting a cell by row label (index) and column label (index) +Use **Pandas Loc Cell Str** for selecting a cell by row label (index) and column label (index). Data type of the labels needs to be specified as shown below: + +![Pandas Loc Cell Str](images/loc_cell_str.png) + +This node outputs the cell value as a string irrespective of the actual cell data type. + ## Joining DataFrames Use **Pandas Join**. You can select from inner, left, right, outer joins. First, use two **Pandas Load CSV** nodes to load two CSVs for the left DataFrame and right DataFrame. diff --git a/examples/workflows/loc_cell_str.json b/examples/workflows/loc_cell_str.json new file mode 100644 index 0000000..a769e45 --- /dev/null +++ b/examples/workflows/loc_cell_str.json @@ -0,0 +1 @@ +{"last_node_id":12,"last_link_id":8,"nodes":[{"id":8,"type":"PandasShowText","pos":[3.62848162651062,1602.7939453125],"size":[210,78.36762237548828],"flags":{},"order":6,"mode":0,"inputs":[{"name":"text","type":"STRING","link":5,"widget":{"name":"text"}}],"outputs":[{"name":"STRING","type":"STRING","links":null,"shape":6}],"properties":{"Node name for S&R":"PandasShowText"},"widgets_values":["","30"]},{"id":3,"type":"PandasCreateWithIndex","pos":[-607.1369018554688,1436.66015625],"size":[210,136.70285034179688],"flags":{},"order":0,"mode":0,"inputs":[],"outputs":[{"name":"STRING","type":"STRING","links":[2,4],"slot_index":0}],"properties":{"Node name for S&R":"PandasCreateWithIndex"},"widgets_values":["index,A,B\nUS,1,10\nFrance,2,20\nGermany,3,30",0]},{"id":7,"type":"PandasLocCellStr","pos":[-294.200927734375,1601.82275390625],"size":[267.4131774902344,156.59359741210938],"flags":{},"order":3,"mode":0,"inputs":[{"name":"dataframe_json","type":"STRING","link":4,"widget":{"name":"dataframe_json"}}],"outputs":[{"name":"STRING","type":"STRING","links":[5],"slot_index":0}],"properties":{"Node name for S&R":"PandasLocCellStr"},"widgets_values":["","Germany","string","B","string"]},{"id":4,"type":"PandasShowDataFrame","pos":[-288.99395751953125,1434.0804443359375],"size":[210,116.62158966064453],"flags":{},"order":2,"mode":0,"inputs":[{"name":"dataframe_json","type":"STRING","link":2,"widget":{"name":"dataframe_json"}}],"outputs":[{"name":"STRING","type":"STRING","links":null,"shape":6}],"properties":{"Node name for S&R":"PandasShowDataFrame"},"widgets_values":[""," A B\nUS 1 10\nFrance 2 20\nGermany 3 30"]},{"id":10,"type":"PandasShowDataFrame","pos":[-293.0326232910156,1839.1920166015625],"size":[210,116.62158966064453],"flags":{},"order":4,"mode":0,"inputs":[{"name":"dataframe_json","type":"STRING","link":7,"widget":{"name":"dataframe_json"}}],"outputs":[{"name":"STRING","type":"STRING","links":null,"shape":6}],"properties":{"Node name for S&R":"PandasShowDataFrame"},"widgets_values":[""," A B\n0 1 100\n1 2 200\n2 3 300"]},{"id":9,"type":"PandasCreate","pos":[-610.7672119140625,1838.9556884765625],"size":[210,113.97640228271484],"flags":{},"order":1,"mode":0,"inputs":[],"outputs":[{"name":"STRING","type":"STRING","links":[7,8],"slot_index":0}],"properties":{"Node name for S&R":"PandasCreate"},"widgets_values":["A,B\n1,100\n2,200\n3,300"]},{"id":12,"type":"PandasShowText","pos":[8.03433609008789,2006.485107421875],"size":[210,78.36762237548828],"flags":{},"order":7,"mode":0,"inputs":[{"name":"text","type":"STRING","link":6,"widget":{"name":"text"}}],"outputs":[{"name":"STRING","type":"STRING","links":null,"shape":6}],"properties":{"Node name for S&R":"PandasShowText"},"widgets_values":["","300"]},{"id":11,"type":"PandasLocCellStr","pos":[-291.8468933105469,2007.802734375],"size":[267.4131774902344,156.59359741210938],"flags":{},"order":5,"mode":0,"inputs":[{"name":"dataframe_json","type":"STRING","link":8,"widget":{"name":"dataframe_json"}}],"outputs":[{"name":"STRING","type":"STRING","links":[6],"slot_index":0}],"properties":{"Node name for S&R":"PandasLocCellStr"},"widgets_values":["","2","int","B","string"]}],"links":[[2,3,0,4,0,"STRING"],[4,3,0,7,0,"STRING"],[5,7,0,8,0,"STRING"],[6,11,0,12,0,"STRING"],[7,9,0,10,0,"STRING"],[8,9,0,11,0,"STRING"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.8639278591604531,"offset":[1001.9775968055815,-1355.3011187363343]},"node_versions":{"data-analysis":"265c91a0caf6a287657b6aa20bfd9ad97728bfe5"},"ue_links":[]},"version":0.4} \ No newline at end of file diff --git a/modules/pandas_wrapper/pandas_loc_cell_str.py b/modules/pandas_wrapper/pandas_loc_cell_str.py new file mode 100644 index 0000000..960c081 --- /dev/null +++ b/modules/pandas_wrapper/pandas_loc_cell_str.py @@ -0,0 +1,57 @@ +from typing import Any, Dict +from io import StringIO +import pandas as pd + +class PandasLocCellStr: + """ + PandasLocCellStr: + A class for selecting a cell from a pandas DataFrame and output as a string. + """ + + @classmethod + def INPUT_TYPES(cls) -> Dict[str, Any]: + """ + Defines the input types for the `cell` function. + + Returns: + Dict[str, Any]: A dictionary specifying required input types. + """ + return { + "required": { + "dataframe_json": ("STRING", {"multiline": True}), + "row_index": ("STRING", {"default": ""}), + "row_index_type":(("string", "int"),), + "column_index": ("STRING", {"default": ""}), + "column_index_type":(("string", "int"),) + } + } + + RETURN_TYPES: tuple = ("STRING",) + FUNCTION: str = "cell" + CATEGORY: str = "Data Analysis" + + def cell(self, dataframe_json: str, + row_index: str, + row_index_type: str, + column_index: str, + column_index_type: str) -> tuple: + """ + Selects specific cell from a pandas DataFrame. + + Args: + dataframe_json (str): A JSON string representation of the DataFrame. + row_index (str): The row index (row label) for the cell. + row_index_type (str): The data type of the row index. + column_index (str): The column index (row label) for the cell. + column_index_type (str): The data type of the column index. + + Returns: + tuple: A tuple containing the value of the cell in string. + """ + # Deserialize JSON string to DataFrame + df = pd.read_json(StringIO(dataframe_json)) + row_index = int(row_index) if row_index_type == "int" else row_index + column_index = int(column_index) if column_index_type == "int" else column_index + + value = df.loc[row_index, column_index] + return (str(value),) diff --git a/pyproject.toml b/pyproject.toml index 506316a..b283524 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "data-analysis" description = "Data analysis custom modules for ComfyUI - Use Pandas & Matplotlib within ComfyUI" -version = "1.0.8" +version = "1.0.9" license = {file = "LICENSE"} [project.urls]