Added Pandas logical operations nodes.

This commit is contained in:
HowToSD
2025-03-07 12:03:58 -08:00
parent 4f0fc89004
commit f918096cb6
31 changed files with 1017 additions and 2 deletions
+27
View File
@@ -14,8 +14,10 @@ from .modules.cda.py_kv_float_create import PyKvFloatCreate
from .modules.cda.py_kv_int_create import PyKvIntCreate
from .modules.cda.py_kv_string_create import PyKvStringCreate
from .modules.cda.py_string_to_datetime import PyStringToDatetime
from .modules.cda.py_string_to_dict import PyStringToDict
from .modules.cda.py_string_to_float import PyStringToFloat
from .modules.cda.py_string_to_int import PyStringToInt
from .modules.cda.py_string_to_list import PyStringToList
from .modules.matplotlib.mpl_bar import MPLBar
from .modules.matplotlib.mpl_line import MPLLine
from .modules.matplotlib.mpl_pie_chart import MPLPieChart
@@ -46,6 +48,7 @@ from .modules.pandas_wrapper.pandas_count import PandasCount
from .modules.pandas_wrapper.pandas_cov import PandasCov
from .modules.pandas_wrapper.pandas_create import PandasCreate
from .modules.pandas_wrapper.pandas_create_from_dict import PandasCreateFromDict
from .modules.pandas_wrapper.pandas_create_from_dict_index_list import PandasCreateFromDictIndexList
from .modules.pandas_wrapper.pandas_create_from_multiple_dict import PandasCreateFromMultipleDict
from .modules.pandas_wrapper.pandas_create_from_numpy import PandasCreateFromNumpy
from .modules.pandas_wrapper.pandas_create_from_tensor import PandasCreateFromTensor
@@ -62,11 +65,14 @@ from .modules.pandas_wrapper.pandas_div_scalar_int import PandasDivScalarInt
from .modules.pandas_wrapper.pandas_div_series import PandasDivSeries
from .modules.pandas_wrapper.pandas_drop_duplicates import PandasDropDuplicates
from .modules.pandas_wrapper.pandas_dropna import PandasDropNA
from .modules.pandas_wrapper.pandas_eq import PandasEq
from .modules.pandas_wrapper.pandas_exp import PandasExp
from .modules.pandas_wrapper.pandas_feature_split_to_numpy import PandasFeatureSplitToNumpy
from .modules.pandas_wrapper.pandas_fillna_scalar_float import PandasFillNAScalarFloat
from .modules.pandas_wrapper.pandas_fillna_scalar_int import PandasFillNAScalarInt
from .modules.pandas_wrapper.pandas_ge import PandasGe
from .modules.pandas_wrapper.pandas_group_by import PandasGroupBy
from .modules.pandas_wrapper.pandas_gt import PandasGt
from .modules.pandas_wrapper.pandas_head import PandasHead
from .modules.pandas_wrapper.pandas_horizontal_concat import PandasHorizontalConcat
from .modules.pandas_wrapper.pandas_horizontal_split import PandasHorizontalSplit
@@ -86,6 +92,7 @@ from .modules.pandas_wrapper.pandas_index_to_string import PandasIndexToString
from .modules.pandas_wrapper.pandas_isna import PandasIsNA
from .modules.pandas_wrapper.pandas_join import PandasJoin
from .modules.pandas_wrapper.pandas_kurtosis import PandasKurtosis
from .modules.pandas_wrapper.pandas_le import PandasLe
from .modules.pandas_wrapper.pandas_load_csv import PandasLoadCSV
from .modules.pandas_wrapper.pandas_load_csv_with_encoding import PandasLoadCSVWithEncoding
from .modules.pandas_wrapper.pandas_load_csv_with_index import PandasLoadCSVWithIndex
@@ -96,6 +103,7 @@ from .modules.pandas_wrapper.pandas_loc_cell_string import PandasLocCellString
from .modules.pandas_wrapper.pandas_loc_row_multiindex_dataframe import PandasLocRowMultiIndexDataFrame
from .modules.pandas_wrapper.pandas_loc_row_series import PandasLocRowSeries
from .modules.pandas_wrapper.pandas_log import PandasLog
from .modules.pandas_wrapper.pandas_lt import PandasLt
from .modules.pandas_wrapper.pandas_max import PandasMax
from .modules.pandas_wrapper.pandas_mean import PandasMean
from .modules.pandas_wrapper.pandas_median import PandasMedian
@@ -106,6 +114,7 @@ from .modules.pandas_wrapper.pandas_mul import PandasMul
from .modules.pandas_wrapper.pandas_mul_scalar_float import PandasMulScalarFloat
from .modules.pandas_wrapper.pandas_mul_scalar_int import PandasMulScalarInt
from .modules.pandas_wrapper.pandas_mul_series import PandasMulSeries
from .modules.pandas_wrapper.pandas_ne import PandasNe
from .modules.pandas_wrapper.pandas_pivot import PandasPivot
from .modules.pandas_wrapper.pandas_pow import PandasPow
from .modules.pandas_wrapper.pandas_pow_scalar_float import PandasPowScalarFloat
@@ -298,6 +307,7 @@ NODE_CLASS_MAPPINGS: Dict[str, Type[T]] = {
"PandasCov": PandasCov,
"PandasCreate": PandasCreate,
"PandasCreateFromDict": PandasCreateFromDict,
"PandasCreateFromDictIndexList": PandasCreateFromDictIndexList,
"PandasCreateFromMultipleDict": PandasCreateFromMultipleDict,
"PandasCreateFromNumpy": PandasCreateFromNumpy,
"PandasCreateFromTensor": PandasCreateFromTensor,
@@ -314,11 +324,14 @@ NODE_CLASS_MAPPINGS: Dict[str, Type[T]] = {
"PandasDivSeries": PandasDivSeries,
"PandasDropDuplicates": PandasDropDuplicates,
"PandasDropNA": PandasDropNA,
"PandasEq": PandasEq,
"PandasExp": PandasExp,
"PandasFeatureSplitToNumpy": PandasFeatureSplitToNumpy,
"PandasFillNAScalarFloat": PandasFillNAScalarFloat,
"PandasFillNAScalarInt": PandasFillNAScalarInt,
"PandasGe": PandasGe,
"PandasGroupBy": PandasGroupBy,
"PandasGt": PandasGt,
"PandasHead": PandasHead,
"PandasHorizontalConcat": PandasHorizontalConcat,
"PandasHorizontalSplit": PandasHorizontalSplit,
@@ -338,6 +351,7 @@ NODE_CLASS_MAPPINGS: Dict[str, Type[T]] = {
"PandasIsNA": PandasIsNA,
"PandasJoin": PandasJoin,
"PandasKurtosis": PandasKurtosis,
"PandasLe": PandasLe,
"PandasLoadCSV": PandasLoadCSV,
"PandasLoadCSVWithEncoding": PandasLoadCSVWithEncoding,
"PandasLoadCSVWithIndex": PandasLoadCSVWithIndex,
@@ -348,6 +362,7 @@ NODE_CLASS_MAPPINGS: Dict[str, Type[T]] = {
"PandasLocRowMultiIndexDataFrame": PandasLocRowMultiIndexDataFrame,
"PandasLocRowSeries": PandasLocRowSeries,
"PandasLog": PandasLog,
"PandasLt": PandasLt,
"PandasMax": PandasMax,
"PandasMean": PandasMean,
"PandasMedian": PandasMedian,
@@ -358,6 +373,7 @@ NODE_CLASS_MAPPINGS: Dict[str, Type[T]] = {
"PandasMulScalarFloat": PandasMulScalarFloat,
"PandasMulScalarInt": PandasMulScalarInt,
"PandasMulSeries": PandasMulSeries,
"PandasNe": PandasNe,
"PandasPivot": PandasPivot,
"PandasPow": PandasPow,
"PandasPowScalarFloat": PandasPowScalarFloat,
@@ -504,8 +520,10 @@ NODE_CLASS_MAPPINGS: Dict[str, Type[T]] = {
"PyKvIntCreate": PyKvIntCreate,
"PyKvStringCreate": PyKvStringCreate,
"PyStringToDatetime": PyStringToDatetime,
"PyStringToDict": PyStringToDict,
"PyStringToFloat": PyStringToFloat,
"PyStringToInt": PyStringToInt,
"PyStringToList": PyStringToList,
"SNSBar": SNSBar,
"SNSBoxplot": SNSBoxplot,
"SNSHeatmap": SNSHeatmap,
@@ -559,6 +577,7 @@ NODE_DISPLAY_NAME_MAPPINGS: Dict[str, str] = {
"PandasCov": "Pandas Cov",
"PandasCreate": "Pandas Create",
"PandasCreateFromDict": "Pandas Create From Dict",
"PandasCreateFromDictIndexList": "Pandas Create From Dict Index List",
"PandasCreateFromMultipleDict": "Pandas Create From Multiple Dict",
"PandasCreateFromNumpy": "Pandas Create From Numpy",
"PandasCreateFromTensor": "Pandas Create From Tensor",
@@ -575,11 +594,14 @@ NODE_DISPLAY_NAME_MAPPINGS: Dict[str, str] = {
"PandasDivSeries": "Pandas Div Series",
"PandasDropDuplicates": "Pandas Drop Duplicates",
"PandasDropNA": "Pandas Drop NA",
"PandasEq": "Pandas Eq",
"PandasExp": "Pandas Exp",
"PandasFeatureSplitToNumpy": "Pandas Feature Split To Numpy",
"PandasFillNAScalarFloat": "Pandas Fill NA Scalar Float",
"PandasFillNAScalarInt": "Pandas Fill NA Scalar Int",
"PandasGe": "Pandas Ge",
"PandasGroupBy": "Pandas Group By",
"PandasGt": "Pandas Gt",
"PandasHead": "Pandas Head",
"PandasHorizontalConcat": "Pandas Horizontal Concat",
"PandasHorizontalSplit": "Pandas Horizontal Split",
@@ -599,6 +621,7 @@ NODE_DISPLAY_NAME_MAPPINGS: Dict[str, str] = {
"PandasIsNA": "Pandas Is NA",
"PandasJoin": "Pandas Join",
"PandasKurtosis": "Pandas Kurtosis",
"PandasLe": "Pandas Le",
"PandasLoadCSV": "Pandas Load CSV",
"PandasLoadCSVWithEncoding": "Pandas Load CSV With Encoding",
"PandasLoadCSVWithIndex": "Pandas Load CSV With Index",
@@ -609,6 +632,7 @@ NODE_DISPLAY_NAME_MAPPINGS: Dict[str, str] = {
"PandasLocRowMultiIndexDataFrame": "Pandas Loc Row MultiIndex DataFrame",
"PandasLocRowSeries": "Pandas Loc Row Series",
"PandasLog": "Pandas Log",
"PandasLt": "Pandas Lt",
"PandasMax": "Pandas Max",
"PandasMean": "Pandas Mean",
"PandasMedian": "Pandas Median",
@@ -619,6 +643,7 @@ NODE_DISPLAY_NAME_MAPPINGS: Dict[str, str] = {
"PandasMulScalarFloat": "Pandas Mul Scalar Float",
"PandasMulScalarInt": "Pandas Mul Scalar Int",
"PandasMulSeries": "Pandas Mul Series",
"PandasNe": "Pandas Ne",
"PandasPivot": "Pandas Pivot",
"PandasPow": "Pandas Pow",
"PandasPowScalarFloat": "Pandas Pow Scalar Float",
@@ -765,8 +790,10 @@ NODE_DISPLAY_NAME_MAPPINGS: Dict[str, str] = {
"PyKvIntCreate": "Py Kv Int Create",
"PyKvStringCreate": "Py Kv String Create",
"PyStringToDatetime": "Py String To Datetime",
"PyStringToDict": "Py String To Dict",
"PyStringToFloat": "Py String To Float",
"PyStringToInt": "Py String To Int",
"PyStringToList": "Py String To List",
"SNSBar": "SNS Bar Chart",
"SNSBoxplot": "SNS Boxplot",
"SNSHeatmap": "SNS Heatmap",
+12
View File
@@ -109,6 +109,7 @@
| [CDA Text Create](cda_text_create.md) | Creates a Python String using a value entered in a multi-line text field. |
| [Pandas Create](pandas_create.md) | Creates a pandas DataFrame using values entered in the text field. |
| [Pandas Create From Dict](pandas_create_from_dict.md) | Creates a pandas DataFrame from a Python dictionary. |
| [Pandas Create From Dict Index List](pandas_create_from_dict_index_list.md) | Creates a pandas DataFrame from a Python dictionary and a list for index. |
| [Pandas Create From Multiple Dict](pandas_create_from_multiple_dict.md) | Creates a pandas DataFrame from multiple Python dictionaries. |
| [Pandas Create From Numpy](pandas_create_from_numpy.md) | Creates a pandas DataFrame from a NumPy ndarray. |
| [Pandas Create From Tensor](pandas_create_from_tensor.md) | Creates a pandas DataFrame from a PyTorch tensor. |
@@ -123,6 +124,15 @@
| [Pandas Save CSV](pandas_save_csv.md) | Saves a PandasDataFrame to a CSV file. |
| [Pandas Save JSON](pandas_save_json.md) | Saves a PandasDataFrame to a JSON file. |
| [Pt Save Model](pt_save_model.md) | A wrapper class for saving a PyTorch model. |
## Logical operations
| Node | Description |
| --- | --- |
| [Pandas Eq](pandas_eq.md) | Determines whether each element in the first pandas DataFrame is equal to the corresponding element in the second DataFrame. |
| [Pandas Ge](pandas_ge.md) | Determines whether each element in the first pandas DataFrame is greater than or equal to the corresponding element in the second DataFrame. |
| [Pandas Gt](pandas_gt.md) | Determines whether each element in the first pandas DataFrame is greater than the corresponding element in the second DataFrame. |
| [Pandas Le](pandas_le.md) | Determines whether each element in the first pandas DataFrame is less than or equal to the corresponding element in the second DataFrame. |
| [Pandas Lt](pandas_lt.md) | Determines whether each element in the first pandas DataFrame is less than the corresponding element in the second DataFrame. |
| [Pandas Ne](pandas_ne.md) | Determines whether each element in the first pandas DataFrame is not equal to the corresponding element in the second DataFrame. |
## Math
| Node | Description |
| --- | --- |
@@ -297,8 +307,10 @@
| [Py Kv Int Create](py_kv_int_create.md) | Creates a Python dictionary with an string key and an integer value. |
| [Py Kv String Create](py_kv_string_create.md) | Creates a Python dictionary with a string key and a string value. |
| [Py String To Datetime](py_string_to_datetime.md) | Converts a Python string to a Python datetime.datetime. |
| [Py String To Dict](py_string_to_dict.md) | Creates a Python dictionary using the string values entered in the text field. |
| [Py String To Float](py_string_to_float.md) | Converts a Python string to a float. |
| [Py String To Int](py_string_to_int.md) | Converts a Python string to an int. |
| [Py String To List](py_string_to_list.md) | Creates a Python list using the string values entered in the text field. |
## Summary statistics
| Node | Description |
| --- | --- |
@@ -1,6 +1,8 @@
# Pandas Create From Dict
Creates a pandas DataFrame from a Python dictionary.
Use `Py String To Dict` node to generate a dict from a string.
## Input
| Name | Data type |
|---|---|
@@ -0,0 +1,21 @@
# Pandas Create From Dict Index List
Creates a pandas DataFrame from a Python dictionary and a list for index.
Use `Py String To Dict` node to generate a dict for cell values from a string.
Use `Py String To List` node to generate a list for index from a string.
## Input
| Name | Data type |
|---|---|
| data | Pydict |
| index | Pylist |
## Output
| Data type |
|---|
| DataFrame |
<HR>
Category: IO
ComfyUI Data Analysis Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
+18
View File
@@ -0,0 +1,18 @@
# Pandas Eq
Determines whether each element in the first pandas DataFrame is equal to the corresponding element in the second DataFrame.
## Input
| Name | Data type |
|---|---|
| a_dataframe | DataFrame |
| b_dataframe | DataFrame |
## Output
| Data type |
|---|
| DataFrame |
<HR>
Category: Logical operations
ComfyUI Data Analysis Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
+18
View File
@@ -0,0 +1,18 @@
# Pandas Ge
Determines whether each element in the first pandas DataFrame is greater than or equal to the corresponding element in the second DataFrame.
## Input
| Name | Data type |
|---|---|
| a_dataframe | DataFrame |
| b_dataframe | DataFrame |
## Output
| Data type |
|---|
| DataFrame |
<HR>
Category: Logical operations
ComfyUI Data Analysis Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
+18
View File
@@ -0,0 +1,18 @@
# Pandas Gt
Determines whether each element in the first pandas DataFrame is greater than the corresponding element in the second DataFrame.
## Input
| Name | Data type |
|---|---|
| a_dataframe | DataFrame |
| b_dataframe | DataFrame |
## Output
| Data type |
|---|
| DataFrame |
<HR>
Category: Logical operations
ComfyUI Data Analysis Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
+18
View File
@@ -0,0 +1,18 @@
# Pandas Le
Determines whether each element in the first pandas DataFrame is less than or equal to the corresponding element in the second DataFrame.
## Input
| Name | Data type |
|---|---|
| a_dataframe | DataFrame |
| b_dataframe | DataFrame |
## Output
| Data type |
|---|
| DataFrame |
<HR>
Category: Logical operations
ComfyUI Data Analysis Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
+18
View File
@@ -0,0 +1,18 @@
# Pandas Lt
Determines whether each element in the first pandas DataFrame is less than the corresponding element in the second DataFrame.
## Input
| Name | Data type |
|---|---|
| a_dataframe | DataFrame |
| b_dataframe | DataFrame |
## Output
| Data type |
|---|
| DataFrame |
<HR>
Category: Logical operations
ComfyUI Data Analysis Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
+18
View File
@@ -0,0 +1,18 @@
# Pandas Ne
Determines whether each element in the first pandas DataFrame is not equal to the corresponding element in the second DataFrame.
## Input
| Name | Data type |
|---|---|
| a_dataframe | DataFrame |
| b_dataframe | DataFrame |
## Output
| Data type |
|---|
| DataFrame |
<HR>
Category: Logical operations
ComfyUI Data Analysis Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
+17
View File
@@ -0,0 +1,17 @@
# Py String To Dict
Creates a Python dictionary using the string values entered in the text field.
## Input
| Name | Data type |
|---|---|
| data | String |
## Output
| Data type |
|---|
| Pydict |
<HR>
Category: Python wrapper
ComfyUI Data Analysis Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
+17
View File
@@ -0,0 +1,17 @@
# Py String To List
Creates a Python list using the string values entered in the text field.
## Input
| Name | Data type |
|---|---|
| data | String |
## Output
| Data type |
|---|
| Pylist |
<HR>
Category: Python wrapper
ComfyUI Data Analysis Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
+1 -1
View File
@@ -35,7 +35,7 @@ class CDAJSONCreate:
data (str): String value in the text field.
Returns:
tuple: A tuple containing a JSON string representation of the DataFrame.
tuple: A tuple containing a JSON string.
"""
# Convert to JSON
json_obj = json.loads(data)
+41
View File
@@ -0,0 +1,41 @@
from typing import Any, Dict
import ast
class PyStringToDict:
"""
Creates a Python dictionary using the string values entered in the text field.
category: Python wrapper
"""
@classmethod
def INPUT_TYPES(cls) -> Dict[str, Any]:
"""
Defines the input types for the `create` function.
Returns:
Dict[str, Any]: A dictionary specifying required input types.
"""
return {
"required": {
"data": ("STRING", {"multiline": True}),
}
}
RETURN_TYPES: tuple = ("PYDICT",)
FUNCTION: str = "f"
CATEGORY: str = "Data Analysis"
def f(self, data: str) -> tuple:
"""
Creates a Python dictionary using the string values entered in the text field.
Args:
data (str): String value in the text field.
Returns:
tuple: A dict converted from the input string.
"""
d = ast.literal_eval(data)
return (d,)
+41
View File
@@ -0,0 +1,41 @@
from typing import Any, List
import ast
class PyStringToList:
"""
Creates a Python list using the string values entered in the text field.
category: Python wrapper
"""
@classmethod
def INPUT_TYPES(cls) -> List[str]:
"""
Defines the input types for the `create` function.
Returns:
List[str, Any]: A list specifying required input types.
"""
return {
"required": {
"data": ("STRING", {"multiline": True}),
}
}
RETURN_TYPES: tuple = ("PYLIST",)
FUNCTION: str = "f"
CATEGORY: str = "Data Analysis"
def f(self, data: str) -> tuple:
"""
Creates a Python list using the string values entered in the text field.
Args:
data (str): String value in the text field.
Returns:
tuple: A list converted from the input string.
"""
d = ast.literal_eval(data)
return (d,)
@@ -12,6 +12,8 @@ class PandasCreateFromDict:
"""
Creates a pandas DataFrame from a Python dictionary.
Use `Py String To Dict` node to generate a dict from a string.
category: IO
"""
@@ -0,0 +1,59 @@
import os
import sys
from typing import Any, Dict, List
import pandas as pd
PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", ".."))
MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules")
sys.path.append(MODULE_ROOT)
from cda.utils import python_dict_first_value_len
class PandasCreateFromDictIndexList:
"""
Creates a pandas DataFrame from a Python dictionary and a list for index.
Use `Py String To Dict` node to generate a dict for cell values from a string.
Use `Py String To List` node to generate a list for index from a string.
category: IO
"""
@classmethod
def INPUT_TYPES(cls) -> Dict[str, Any]:
"""
Defines the input types for the `create` function.
Returns:
Dict[str, Any]: A dictionary specifying required input types.
"""
return {
"required": {
"data": ("PYDICT", {}),
"index": ("PYLIST", {}),
}
}
RETURN_TYPES: tuple = ("DATAFRAME",)
FUNCTION: str = "f"
CATEGORY: str = "Data Analysis"
def f(self, data: Dict, index: List) -> tuple:
"""
Creates a pandas DataFrame from a Python dictionary.
Args:
data (Dict): A Python dictionary containing cell values.
index (List): A Python list containing index.
Returns:
tuple: A tuple containing a the DataFrame.
"""
if not data:
df = pd.DataFrame() # Return an empty DataFrame if no data is provided.
else:
if not list:
value_length = python_dict_first_value_len(data)
df = pd.DataFrame(data, index=list(range(value_length)))
else:
df = pd.DataFrame(data, index=index)
return (df,)
+43
View File
@@ -0,0 +1,43 @@
from typing import Any, Dict
import pandas as pd
class PandasEq:
"""
Determines whether each element in the first pandas DataFrame is equal to the corresponding element in the second DataFrame.
category: Logical operations
"""
@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": {
"a_dataframe": ("DATAFRAME", {}),
"b_dataframe": ("DATAFRAME", {})
}
}
RETURN_TYPES: tuple = ("DATAFRAME",)
FUNCTION: str = "f"
CATEGORY: str = "Data Analysis"
def f(self, a_dataframe: pd.DataFrame, b_dataframe: pd.DataFrame) -> tuple:
"""
Determines whether each element in the first pandas DataFrame is equal to the corresponding element in the second DataFrame.
Args:
a_dataframe (DataFrame): The left DataFrame.
b_dataframe (DataFrame): The right DataFrame.
Returns:
tuple: A tuple containing the DataFrame containing the result of operation.
"""
df_out = a_dataframe.eq(b_dataframe)
return (df_out,)
+43
View File
@@ -0,0 +1,43 @@
from typing import Any, Dict
import pandas as pd
class PandasGe:
"""
Determines whether each element in the first pandas DataFrame is greater than or equal to the corresponding element in the second DataFrame.
category: Logical operations
"""
@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": {
"a_dataframe": ("DATAFRAME", {}),
"b_dataframe": ("DATAFRAME", {})
}
}
RETURN_TYPES: tuple = ("DATAFRAME",)
FUNCTION: str = "f"
CATEGORY: str = "Data Analysis"
def f(self, a_dataframe: pd.DataFrame, b_dataframe: pd.DataFrame) -> tuple:
"""
Determines whether each element in the first pandas DataFrame is greater than or equal to the corresponding element in the second DataFrame.
Args:
a_dataframe (DataFrame): The left DataFrame.
b_dataframe (DataFrame): The right DataFrame.
Returns:
tuple: A tuple containing the DataFrame containing the result of operation.
"""
df_out = a_dataframe.ge(b_dataframe)
return (df_out,)
+43
View File
@@ -0,0 +1,43 @@
from typing import Any, Dict
import pandas as pd
class PandasGt:
"""
Determines whether each element in the first pandas DataFrame is greater than the corresponding element in the second DataFrame.
category: Logical operations
"""
@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": {
"a_dataframe": ("DATAFRAME", {}),
"b_dataframe": ("DATAFRAME", {})
}
}
RETURN_TYPES: tuple = ("DATAFRAME",)
FUNCTION: str = "f"
CATEGORY: str = "Data Analysis"
def f(self, a_dataframe: pd.DataFrame, b_dataframe: pd.DataFrame) -> tuple:
"""
Determines whether each element in the first pandas DataFrame is greater than the corresponding element in the second DataFrame.
Args:
a_dataframe (DataFrame): The left DataFrame.
b_dataframe (DataFrame): The right DataFrame.
Returns:
tuple: A tuple containing the DataFrame containing the result of operation.
"""
df_out = a_dataframe.gt(b_dataframe)
return (df_out,)
+43
View File
@@ -0,0 +1,43 @@
from typing import Any, Dict
import pandas as pd
class PandasLe:
"""
Determines whether each element in the first pandas DataFrame is less than or equal to the corresponding element in the second DataFrame.
category: Logical operations
"""
@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": {
"a_dataframe": ("DATAFRAME", {}),
"b_dataframe": ("DATAFRAME", {})
}
}
RETURN_TYPES: tuple = ("DATAFRAME",)
FUNCTION: str = "f"
CATEGORY: str = "Data Analysis"
def f(self, a_dataframe: pd.DataFrame, b_dataframe: pd.DataFrame) -> tuple:
"""
Determines whether each element in the first pandas DataFrame is less than or equal to the corresponding element in the second DataFrame.
Args:
a_dataframe (DataFrame): The left DataFrame.
b_dataframe (DataFrame): The right DataFrame.
Returns:
tuple: A tuple containing the DataFrame containing the result of operation.
"""
df_out = a_dataframe.le(b_dataframe)
return (df_out,)
+43
View File
@@ -0,0 +1,43 @@
from typing import Any, Dict
import pandas as pd
class PandasLt:
"""
Determines whether each element in the first pandas DataFrame is less than the corresponding element in the second DataFrame.
category: Logical operations
"""
@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": {
"a_dataframe": ("DATAFRAME", {}),
"b_dataframe": ("DATAFRAME", {})
}
}
RETURN_TYPES: tuple = ("DATAFRAME",)
FUNCTION: str = "f"
CATEGORY: str = "Data Analysis"
def f(self, a_dataframe: pd.DataFrame, b_dataframe: pd.DataFrame) -> tuple:
"""
Determines whether each element in the first pandas DataFrame is less than the corresponding element in the second DataFrame.
Args:
a_dataframe (DataFrame): The left DataFrame.
b_dataframe (DataFrame): The right DataFrame.
Returns:
tuple: A tuple containing the DataFrame containing the result of operation.
"""
df_out = a_dataframe.lt(b_dataframe)
return (df_out,)
+43
View File
@@ -0,0 +1,43 @@
from typing import Any, Dict
import pandas as pd
class PandasNe:
"""
Determines whether each element in the first pandas DataFrame is not equal to the corresponding element in the second DataFrame.
category: Logical operations
"""
@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": {
"a_dataframe": ("DATAFRAME", {}),
"b_dataframe": ("DATAFRAME", {})
}
}
RETURN_TYPES: tuple = ("DATAFRAME",)
FUNCTION: str = "f"
CATEGORY: str = "Data Analysis"
def f(self, a_dataframe: pd.DataFrame, b_dataframe: pd.DataFrame) -> tuple:
"""
Determines whether each element in the first pandas DataFrame is not equal to the corresponding element in the second DataFrame.
Args:
a_dataframe (DataFrame): The left DataFrame.
b_dataframe (DataFrame): The right DataFrame.
Returns:
tuple: A tuple containing the DataFrame containing the result of operation.
"""
df_out = a_dataframe.ne(b_dataframe)
return (df_out,)
+1 -1
View File
@@ -1,7 +1,7 @@
[project]
name = "data-analysis"
description = "Data analysis custom modules for ComfyUI – Integrates Pandas, Seaborn and Matplotlib into ComfyUI, featuring extensive PyTorch wrapper nodes for seamless tensor operations. Experimental PyTorch model training was added in v2.0."
version = "2.0.8"
version = "2.0.9"
license = {file = "LICENSE"}
[project.urls]
@@ -0,0 +1,62 @@
import os
import sys
import unittest
import pandas as pd
PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", ".."))
MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules")
sys.path.append(MODULE_ROOT)
from pandas_wrapper.pandas_create_from_dict_index_list import PandasCreateFromDictIndexList
class TestPandasCreateFromDictIndexList(unittest.TestCase):
def setUp(self):
"""Set up test data."""
self.node = PandasCreateFromDictIndexList()
self.test_cases = [
# Test with a standard dictionary and provided index
(
{"a": [1, 2, 3], "b": [4, 5, 6]},
["row1", "row2", "row3"],
pd.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]}, index=["row1", "row2", "row3"])
),
# Test with an empty dictionary (should return an empty DataFrame)
(
{},
["row1", "row2"],
pd.DataFrame()
),
# Test with missing index (should use default range index)
(
{"a": [7, 8, 9]},
None,
pd.DataFrame({"a": [7, 8, 9]}, index=[0, 1, 2])
),
# Test with integer index values
(
{"x": [10, 20], "y": [30, 40]},
[100, 101],
pd.DataFrame({"x": [10, 20], "y": [30, 40]}, index=[100, 101])
),
# Test with a single column and mismatched index length (should raise an error)
(
{"c": [1, 2]},
["only_one_row"],
ValueError # Expecting an error because index length doesn't match data length
),
]
def test_create_dataframe(self):
"""Test creating a pandas DataFrame from a dictionary with an index."""
for data, index, expected in self.test_cases:
with self.subTest(data=data, index=index):
if expected is ValueError:
with self.assertRaises(ValueError):
self.node.f(data, index)
else:
retval = self.node.f(data, index)
self.assertIsInstance(retval, tuple, "Return value should be a tuple.")
self.assertEqual(len(retval), 1, "Return tuple should have a single DataFrame.")
pd.testing.assert_frame_equal(retval[0], expected)
if __name__ == "__main__":
unittest.main()
+58
View File
@@ -0,0 +1,58 @@
import os
import sys
import unittest
import pandas as pd
PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", ".."))
MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules")
sys.path.append(MODULE_ROOT)
from pandas_wrapper.pandas_eq import PandasEq
class TestPandasEq(unittest.TestCase):
def setUp(self):
"""Set up test data."""
self.node = PandasEq()
self.test_cases = [
# Test where all values are True (a == b)
(
pd.DataFrame({"a": [1.5, 2.5]}, index=["row1", "row2"]),
pd.DataFrame({"a": [1.5, 2.5]}, index=["row1", "row2"]),
pd.DataFrame({"a": [True, True]}, index=["row1", "row2"])
),
# Test with mixed float and integer (True for all)
(
pd.DataFrame({"a": [3.0, 4]}, index=[0, 1]), # Second value is an integer
pd.DataFrame({"a": [3.0, 4]}, index=[0, 1]), # Second value is an integer
pd.DataFrame({"a": [True, True]}, index=[0, 1])
),
# Test with integer column labels (True for all)
(
pd.DataFrame({1: [10.0, 20]}, index=[0, 1]), # Second value is an integer
pd.DataFrame({1: [10.0, 20]}, index=[0, 1]), # Second value is an integer
pd.DataFrame({1: [True, True]}, index=[0, 1])
),
# Test with a False case (a != b)
(
pd.DataFrame({"a": [7.0]}, index=["row1"]),
pd.DataFrame({"a": [7.5]}, index=["row1"]),
pd.DataFrame({"a": [False]}, index=["row1"])
),
# Another False case with an integer column label
(
pd.DataFrame({2: [9]}, index=["row1"]), # Integer value
pd.DataFrame({2: [10]}, index=["row1"]), # Different integer value
pd.DataFrame({2: [False]}, index=["row1"])
),
]
def test_eq_operation(self):
"""Test equality operation between two pandas DataFrames."""
for df_a, df_b, expected in self.test_cases:
with self.subTest(df_a=df_a, df_b=df_b):
retval = self.node.f(df_a, df_b)
self.assertIsInstance(retval, tuple, "Return value should be a tuple.")
self.assertEqual(len(retval), 1, "Return tuple should have a single DataFrame.")
pd.testing.assert_frame_equal(retval[0], expected)
if __name__ == "__main__":
unittest.main()
+58
View File
@@ -0,0 +1,58 @@
import os
import sys
import unittest
import pandas as pd
PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", ".."))
MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules")
sys.path.append(MODULE_ROOT)
from pandas_wrapper.pandas_ge import PandasGe
class TestPandasGe(unittest.TestCase):
def setUp(self):
"""Set up test data."""
self.node = PandasGe()
self.test_cases = [
# Test where all values are True (a >= b)
(
pd.DataFrame({"a": [2.0, 3.0]}, index=["row1", "row2"]),
pd.DataFrame({"a": [1.5, 2.5]}, index=["row1", "row2"]),
pd.DataFrame({"a": [True, True]}, index=["row1", "row2"])
),
# Test with equality and lt
(
pd.DataFrame({"a": [2.5, 4.5]}, index=[0, 1]),
pd.DataFrame({"a": [3.0, 4.5]}, index=[0, 1]),
pd.DataFrame({"a": [False, True]}, index=[0, 1])
),
# Test with integer column labels (True)
(
pd.DataFrame({1: [15.0, 25.0]}, index=[0, 1]),
pd.DataFrame({1: [10.0, 20.0]}, index=[0, 1]),
pd.DataFrame({1: [True, True]}, index=[0, 1])
),
# Test with a False case (a < b)
(
pd.DataFrame({"a": [7.0]}, index=["row1"]),
pd.DataFrame({"a": [7.5]}, index=["row1"]),
pd.DataFrame({"a": [False]}, index=["row1"])
),
# True case with an integer column label
(
pd.DataFrame({2: [9.5]}, index=["row1"]),
pd.DataFrame({2: [9.5]}, index=["row1"]),
pd.DataFrame({2: [True]}, index=["row1"])
),
]
def test_ge_operation(self):
"""Test greater-than-or-equal operation between two pandas DataFrames."""
for df_a, df_b, expected in self.test_cases:
with self.subTest(df_a=df_a, df_b=df_b):
retval = self.node.f(df_a, df_b)
self.assertIsInstance(retval, tuple, "Return value should be a tuple.")
self.assertEqual(len(retval), 1, "Return tuple should have a single DataFrame.")
pd.testing.assert_frame_equal(retval[0], expected)
if __name__ == "__main__":
unittest.main()
+58
View File
@@ -0,0 +1,58 @@
import os
import sys
import unittest
import pandas as pd
PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", ".."))
MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules")
sys.path.append(MODULE_ROOT)
from pandas_wrapper.pandas_gt import PandasGt
class TestPandasGt(unittest.TestCase):
def setUp(self):
"""Set up test data."""
self.node = PandasGt()
self.test_cases = [
# Test where all values are True
(
pd.DataFrame({"a": [2.5, 3.5]}, index=["row1", "row2"]),
pd.DataFrame({"a": [2.0, 3.0]}, index=["row1", "row2"]),
pd.DataFrame({"a": [True, True]}, index=["row1", "row2"])
),
# Test with mixed result
(
pd.DataFrame({"a": [3.6, 4.9]}, index=[0, 1]),
pd.DataFrame({"a": [3.5, 5.0]}, index=[0, 1]),
pd.DataFrame({"a": [True, False]}, index=[0, 1])
),
# Test with integer column labels
(
pd.DataFrame({1: [14.0, 26.0]}, index=[0, 1]),
pd.DataFrame({1: [15.0, 25.0]}, index=[0, 1]),
pd.DataFrame({1: [False, True]}, index=[0, 1])
),
# Test with a False case (a < b)
(
pd.DataFrame({"a": [6.0]}, index=["row1"]),
pd.DataFrame({"a": [7.0]}, index=["row1"]),
pd.DataFrame({"a": [False]}, index=["row1"])
),
# Another False case with an integer column label
(
pd.DataFrame({2: [7.5]}, index=["row1"]),
pd.DataFrame({2: [8.0]}, index=["row1"]),
pd.DataFrame({2: [False]}, index=["row1"])
),
]
def test_gt_operation(self):
"""Test greater-than operation between two pandas DataFrames."""
for df_a, df_b, expected in self.test_cases:
with self.subTest(df_a=df_a, df_b=df_b):
retval = self.node.f(df_a, df_b)
self.assertIsInstance(retval, tuple, "Return value should be a tuple.")
self.assertEqual(len(retval), 1, "Return tuple should have a single DataFrame.")
pd.testing.assert_frame_equal(retval[0], expected)
if __name__ == "__main__":
unittest.main()
+58
View File
@@ -0,0 +1,58 @@
import os
import sys
import unittest
import pandas as pd
PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", ".."))
MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules")
sys.path.append(MODULE_ROOT)
from pandas_wrapper.pandas_le import PandasLe
class TestPandasLe(unittest.TestCase):
def setUp(self):
"""Set up test data."""
self.node = PandasLe()
self.test_cases = [
# Test where all values are True
(
pd.DataFrame({"a": [1.5, 2.5]}, index=["row1", "row2"]),
pd.DataFrame({"a": [2.0, 2.5]}, index=["row1", "row2"]),
pd.DataFrame({"a": [True, True]}, index=["row1", "row2"])
),
# Test with integer (still True)
(
pd.DataFrame({"a": [3, 4]}, index=[0, 1]),
pd.DataFrame({"a": [3, 4]}, index=[0, 1]),
pd.DataFrame({"a": [True, True]}, index=[0, 1])
),
# Test with integer column labels (True)
(
pd.DataFrame({1: [10.0, 20.0]}, index=[0, 1]),
pd.DataFrame({1: [15.0, 20.0]}, index=[0, 1]),
pd.DataFrame({1: [True, True]}, index=[0, 1])
),
# Test with a False case (a > b)
(
pd.DataFrame({"a": [7.0]}, index=["row1"]),
pd.DataFrame({"a": [6.5]}, index=["row1"]),
pd.DataFrame({"a": [False]}, index=["row1"])
),
# Another False case with an integer column label
(
pd.DataFrame({2: [9.5]}, index=["row1"]),
pd.DataFrame({2: [8.0]}, index=["row1"]),
pd.DataFrame({2: [False]}, index=["row1"])
),
]
def test_le_operation(self):
"""Test less-than-or-equal operation between two pandas DataFrames."""
for df_a, df_b, expected in self.test_cases:
with self.subTest(df_a=df_a, df_b=df_b):
retval = self.node.f(df_a, df_b)
self.assertIsInstance(retval, tuple, "Return value should be a tuple.")
self.assertEqual(len(retval), 1, "Return tuple should have a single DataFrame.")
pd.testing.assert_frame_equal(retval[0], expected)
if __name__ == "__main__":
unittest.main()
+58
View File
@@ -0,0 +1,58 @@
import os
import sys
import unittest
import pandas as pd
PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", ".."))
MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules")
sys.path.append(MODULE_ROOT)
from pandas_wrapper.pandas_lt import PandasLt
class TestPandasLt(unittest.TestCase):
def setUp(self):
"""Set up test data."""
self.node = PandasLt()
self.test_cases = [
# Test where all values are True
(
pd.DataFrame({"a": [1.5, 2.5]}, index=["row1", "row2"]),
pd.DataFrame({"a": [2.0, 3.0]}, index=["row1", "row2"]),
pd.DataFrame({"a": [True, True]}, index=["row1", "row2"])
),
# Test with integer (still True)
(
pd.DataFrame({"a": [3, 40]}, index=[0, 1]),
pd.DataFrame({"a": [4, 50]}, index=[0, 1]),
pd.DataFrame({"a": [True, True]}, index=[0, 1])
),
# Test with integer column labels
(
pd.DataFrame({1: [10.0, 20.0]}, index=[0, 1]),
pd.DataFrame({1: [15.0, 20.0]}, index=[0, 1]),
pd.DataFrame({1: [True, False]}, index=[0, 1])
),
# Test with a False case (a >= b)
(
pd.DataFrame({"a": [7.0]}, index=["row1"]),
pd.DataFrame({"a": [7.0]}, index=["row1"]),
pd.DataFrame({"a": [False]}, index=["row1"])
),
# Another False case with an integer column label
(
pd.DataFrame({2: [9.5]}, index=["row1"]),
pd.DataFrame({2: [8.0]}, index=["row1"]),
pd.DataFrame({2: [False]}, index=["row1"])
),
]
def test_lt_operation(self):
"""Test less-than operation between two pandas DataFrames."""
for df_a, df_b, expected in self.test_cases:
with self.subTest(df_a=df_a, df_b=df_b):
retval = self.node.f(df_a, df_b)
self.assertIsInstance(retval, tuple, "Return value should be a tuple.")
self.assertEqual(len(retval), 1, "Return tuple should have a single DataFrame.")
pd.testing.assert_frame_equal(retval[0], expected)
if __name__ == "__main__":
unittest.main()
+58
View File
@@ -0,0 +1,58 @@
import os
import sys
import unittest
import pandas as pd
PROJECT_ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", ".."))
MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules")
sys.path.append(MODULE_ROOT)
from pandas_wrapper.pandas_ne import PandasNe
class TestPandasNe(unittest.TestCase):
def setUp(self):
"""Set up test data."""
self.node = PandasNe()
self.test_cases = [
# Test where all values are True (a != b)
(
pd.DataFrame({"a": [1.5, 2.5]}, index=["row1", "row2"]),
pd.DataFrame({"a": [2.0, 3.0]}, index=["row1", "row2"]),
pd.DataFrame({"a": [True, True]}, index=["row1", "row2"])
),
# Test with mixed float and integer (True for all)
(
pd.DataFrame({"a": [3.0, 4]}, index=[0, 1]), # Second value is an integer
pd.DataFrame({"a": [3.5, 5]}, index=[0, 1]), # Second value is an integer
pd.DataFrame({"a": [True, True]}, index=[0, 1])
),
# Test with integer column labels (True for all)
(
pd.DataFrame({1: [10.0, 20]}, index=[0, 1]), # Second value is an integer
pd.DataFrame({1: [15.0, 25]}, index=[0, 1]), # Second value is an integer
pd.DataFrame({1: [True, True]}, index=[0, 1])
),
# Test with a False case (a == b)
(
pd.DataFrame({"a": [7.0]}, index=["row1"]),
pd.DataFrame({"a": [7.0]}, index=["row1"]),
pd.DataFrame({"a": [False]}, index=["row1"])
),
# Another False case with an integer column label
(
pd.DataFrame({2: [9]}, index=["row1"]), # Integer value
pd.DataFrame({2: [9]}, index=["row1"]), # Integer value
pd.DataFrame({2: [False]}, index=["row1"])
),
]
def test_ne_operation(self):
"""Test not-equal operation between two pandas DataFrames."""
for df_a, df_b, expected in self.test_cases:
with self.subTest(df_a=df_a, df_b=df_b):
retval = self.node.f(df_a, df_b)
self.assertIsInstance(retval, tuple, "Return value should be a tuple.")
self.assertEqual(len(retval), 1, "Return tuple should have a single DataFrame.")
pd.testing.assert_frame_equal(retval[0], expected)
if __name__ == "__main__":
unittest.main()