Added Pandas XS node.
This commit is contained in:
@@ -95,6 +95,7 @@ from .modules.pandas_wrapper.pandas_transpose import PandasTranspose
|
||||
from .modules.pandas_wrapper.pandas_var import PandasVar
|
||||
from .modules.pandas_wrapper.pandas_vertical_concat import PandasVerticalConcat
|
||||
from .modules.pandas_wrapper.pandas_vertical_split import PandasVerticalSplit
|
||||
from .modules.pandas_wrapper.pandas_xs import PandasXs
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
@@ -199,6 +200,7 @@ NODE_CLASS_MAPPINGS: Dict[str, Type[T]] = {
|
||||
"PandasVar": PandasVar,
|
||||
"PandasVerticalConcat": PandasVerticalConcat,
|
||||
"PandasVerticalSplit": PandasVerticalSplit,
|
||||
"PandasXs": PandasXs,
|
||||
}
|
||||
|
||||
|
||||
@@ -303,6 +305,7 @@ NODE_DISPLAY_NAME_MAPPINGS: Dict[str, str] = {
|
||||
"PandasVar": "Pandas Var",
|
||||
"PandasVerticalConcat": "Pandas Vertical Concat",
|
||||
"PandasVerticalSplit": "Pandas Vertical Split",
|
||||
"PandasXs": "Pandas Xs",
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
| [Pandas Loc Row Series](pandas_loc_row_series.md) | Selects a row from a pandas DataFrame and output as a Series. |
|
||||
| [Pandas Select Columns](pandas_select_columns.md) | Selects specific columns from a pandas DataFrame. |
|
||||
| [Pandas Select Rows](pandas_select_rows.md) | Selects specific rows from a pandas DataFrame based on a condition. |
|
||||
| [Pandas Xs](pandas_xs.md) | Selects a subset of a Pandas DataFrame using specified index labels or positions. |
|
||||
## Data type conversion
|
||||
| Node | Description |
|
||||
| --- | --- |
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
# Pandas Xs
|
||||
Selects a subset of a Pandas DataFrame using specified index labels or positions.
|
||||
|
||||
This function extracts a portion of a DataFrame based on MultiIndex labels (row indices or column labels).
|
||||
|
||||
Users must specify:
|
||||
* The labels to select (comma-separated for multiple labels).
|
||||
* The level(s) within the MultiIndex (integer positions).
|
||||
* The axis (whether selecting from rows or columns).
|
||||
|
||||
**Understanding "Level":**
|
||||
In a MultiIndex DataFrame, a level refers to the hierarchical position of an index within the MultiIndex, which can be referenced using a 0-based integer position or an assigned level name.
|
||||
Selecting the level using an integer position is similar to integer-based selection in `iloc`.
|
||||
|
||||
When specifying a label, Pandas needs to know which level of the MultiIndex to search.
|
||||
For example, if selecting "dog" as a row label and the DataFrame has multiple index levels,
|
||||
you must indicate whether to look in the first index (level 0) or the second index (level 1).
|
||||
|
||||
If selecting multiple labels, their corresponding levels should be provided as a comma-separated list.
|
||||
|
||||
Example:
|
||||
Given a DataFrame with a 3-level MultiIndex, the first index is at level 0, the second at level 1, and the third at level 2. Selecting "dog" and "brown" at levels 1 and 2 requires specifying 1, 2 in the Level field of the node. These values are internally converted into a list and passed to Pandas.
|
||||
|
||||
The `axis` field specifies whether selection applies to row indices (`axis=0`) or column labels (`axis=1`).
|
||||
|
||||
## Input
|
||||
| Name | Data type |
|
||||
|---|---|
|
||||
| dataframe | DataFrame |
|
||||
| row_or_column_label | String |
|
||||
| label_type | |
|
||||
| level | String |
|
||||
| level_type | |
|
||||
| axis | |
|
||||
|
||||
## Output
|
||||
| Data type |
|
||||
|---|
|
||||
| DataFrame |
|
||||
|
||||
<HR>
|
||||
Category: Data subset selection
|
||||
|
||||
ComfyUI Data Analysis Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
|
||||
@@ -60,12 +60,14 @@ class PandasLocRowMultiIndexDataFrame:
|
||||
ind_list = [int(ind) for ind in ind_list]
|
||||
|
||||
ind_tuple = tuple(ind_list) # Convert the list to a tuple
|
||||
if len(ind_tuple) == 1: # Do not enclose in tuple if only 1 index is specified
|
||||
ind = ind_tuple[0]
|
||||
else:
|
||||
ind = ind_tuple
|
||||
# Ensure partial indexing is supported by adding slice(None) for missing levels
|
||||
if len(ind_tuple) < dataframe.index.nlevels:
|
||||
filler_count = dataframe.index.nlevels - len(ind_tuple)
|
||||
for _ in range(filler_count):
|
||||
ind_tuple += (slice(None),)
|
||||
|
||||
# We need to wrap it to get the DataFrame. Otherwise, we will get a Series.
|
||||
ind_list = [ind]
|
||||
value = dataframe.loc[ind_list]
|
||||
return (value,)
|
||||
result = dataframe.loc[ind_tuple]
|
||||
if isinstance(result, pd.Series): # loc can return Series so convert to DataFrame
|
||||
result = result.to_frame().T
|
||||
|
||||
return (result,)
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
from typing import Any, Dict
|
||||
import pandas as pd
|
||||
|
||||
class PandasXs:
|
||||
"""
|
||||
Selects a subset of a Pandas DataFrame using specified index labels or positions.
|
||||
|
||||
This function extracts a portion of a DataFrame based on MultiIndex labels (row indices or column labels).
|
||||
|
||||
Users must specify:
|
||||
* The labels to select (comma-separated for multiple labels).
|
||||
* The level(s) within the MultiIndex (integer positions).
|
||||
* The axis (whether selecting from rows or columns).
|
||||
|
||||
**Understanding "Level":**
|
||||
In a MultiIndex DataFrame, a level refers to the hierarchical position of an index within the MultiIndex, which can be referenced using a 0-based integer position or an assigned level name.
|
||||
Selecting the level using an integer position is similar to integer-based selection in `iloc`.
|
||||
|
||||
When specifying a label, Pandas needs to know which level of the MultiIndex to search.
|
||||
For example, if selecting "dog" as a row label and the DataFrame has multiple index levels,
|
||||
you must indicate whether to look in the first index (level 0) or the second index (level 1).
|
||||
|
||||
If selecting multiple labels, their corresponding levels should be provided as a comma-separated list.
|
||||
|
||||
Example:
|
||||
Given a DataFrame with a 3-level MultiIndex, the first index is at level 0, the second at level 1, and the third at level 2. Selecting "dog" and "brown" at levels 1 and 2 requires specifying 1, 2 in the Level field of the node. These values are internally converted into a list and passed to Pandas.
|
||||
|
||||
The `axis` field specifies whether selection applies to row indices (`axis=0`) or column labels (`axis=1`).
|
||||
|
||||
category: Data subset selection
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Defines the input types for the function.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary specifying required input types.
|
||||
"""
|
||||
return {
|
||||
"required": {
|
||||
"dataframe": ("DATAFRAME", {}),
|
||||
"row_or_column_label": ("STRING", {"default": ""}),
|
||||
"label_type":(("string", "int"),),
|
||||
"level": ("STRING", {"default": ""}),
|
||||
"level_type":(("int", "string"),),
|
||||
"axis": (("index", "columns"),)
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES: tuple = ("DATAFRAME",)
|
||||
FUNCTION: str = "f"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def f(self, dataframe: pd.DataFrame,
|
||||
row_or_column_label: str,
|
||||
label_type: str,
|
||||
level: str,
|
||||
level_type: str,
|
||||
axis: str) -> tuple:
|
||||
"""
|
||||
Selects a subset of a Pandas DataFrame using specified index labels or positions.
|
||||
|
||||
Args:
|
||||
dataframe (DataFrame): The DataFrame.
|
||||
row_or_column (str): A comma-separated MultiIndex label for the row or label.
|
||||
label_type (str): The data type of the row index or column label.
|
||||
level (str): A comma-separated level list for the MultiIndex to select.
|
||||
level_type (str): The data type of the level.
|
||||
axis (str): Specifies whether labels are for a row or column.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing the Pandas DataFrame.
|
||||
"""
|
||||
# Extract index list
|
||||
# We need to pass a tuple of MultiIndex.
|
||||
# e.g. if the first index is A, second is B, we need to pass:
|
||||
# ("A", "B")
|
||||
ind_list = [e.strip() for e in row_or_column_label.split(",")]
|
||||
|
||||
# This will throw an exception if the MultiIndex is not an int.
|
||||
if label_type == "int":
|
||||
ind_list = [int(e) for e in ind_list]
|
||||
|
||||
ind_tuple = tuple(ind_list) # Convert the list to a tuple
|
||||
if len(ind_tuple) == 1: # Do not enclose in tuple if only 1 index is specified
|
||||
ind = ind_tuple[0]
|
||||
else:
|
||||
ind = ind_tuple
|
||||
|
||||
# Extract level list
|
||||
if len(level) == 0:
|
||||
level = None
|
||||
else:
|
||||
level_list = [e.strip() for e in level.split(",")]
|
||||
|
||||
# This will throw an exception if the MultiIndex is not an int.
|
||||
if level_type == "int":
|
||||
level_list = [int(e) for e in level_list]
|
||||
|
||||
if len(level_list) == 1:
|
||||
level = level_list[0]
|
||||
else:
|
||||
level = level_list
|
||||
|
||||
df_out = dataframe.sort_index().xs(
|
||||
ind,
|
||||
level=level,
|
||||
axis=axis
|
||||
)
|
||||
return (df_out,)
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "data-analysis"
|
||||
description = "Data analysis custom modules for ComfyUI - Use Pandas & Matplotlib within ComfyUI"
|
||||
version = "1.1.17"
|
||||
version = "1.1.18"
|
||||
license = {file = "LICENSE"}
|
||||
|
||||
[project.urls]
|
||||
|
||||
Reference in New Issue
Block a user