Added Pandas Create from Tensor, Pandas Rename Advanced nodes. Added an option to reindex the column in Pandas Horizontal Concat node.

This commit is contained in:
HowToSD
2025-03-01 16:45:41 -08:00
parent ce52e12a5d
commit 62e4f6efb8
23 changed files with 526 additions and 9 deletions
+3
View File
@@ -4,6 +4,7 @@ from io import StringIO
import pandas as pd
from .common import common_input_types
from .util import plot_post_steps
from ..pandas_wrapper.utils import column_label_string_to_target_type
class MPLBar:
"""
@@ -56,6 +57,8 @@ class MPLBar:
# Create the plot
fig, ax = plt.subplots()
x_column_name = column_label_string_to_target_type(df, x_column_name)
y_column_name = column_label_string_to_target_type(df, y_column_name)
ax.bar(df[x_column_name], df[y_column_name])
return plot_post_steps(
+3
View File
@@ -4,6 +4,7 @@ from io import StringIO
import pandas as pd
from .common import common_input_types
from .util import plot_post_steps
from ..pandas_wrapper.utils import column_label_string_to_target_type
class MPLLine:
"""
@@ -53,6 +54,8 @@ class MPLLine:
"""
df = dataframe
x_column_name = column_label_string_to_target_type(df, x_column_name)
y_column_name = column_label_string_to_target_type(df, y_column_name)
# Create the plot
fig, ax = plt.subplots()
+3
View File
@@ -2,6 +2,7 @@ from typing import Any, Dict
from matplotlib import pyplot as plt
import pandas as pd
from .util import plot_post_steps
from ..pandas_wrapper.utils import column_label_string_to_target_type
class MPLPieChart:
"""
@@ -54,6 +55,8 @@ class MPLPieChart:
"""
df = dataframe
label_column_name = column_label_string_to_target_type(df, label_column_name)
data_column_name = column_label_string_to_target_type(df, data_column_name)
# Create the plot
fig, ax = plt.subplots()
+3
View File
@@ -4,6 +4,7 @@ from io import StringIO
import pandas as pd
from .common import common_input_types
from .util import plot_post_steps
from ..pandas_wrapper.utils import column_label_string_to_target_type
class MPLScatter:
"""
@@ -53,6 +54,8 @@ class MPLScatter:
"""
df = dataframe
x_column_name = column_label_string_to_target_type(df, x_column_name)
y_column_name = column_label_string_to_target_type(df, y_column_name)
# Create the plot
fig, ax = plt.subplots()
@@ -0,0 +1,48 @@
from typing import Any, Dict
import pandas as pd
import torch
class PandasCreateFromTensor:
"""
Creates a pandas DataFrame from a PyTorch tensor.
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": {
"tens": ("TENSOR", {}),
}
}
RETURN_TYPES: tuple = ("DATAFRAME",)
FUNCTION: str = "f"
CATEGORY: str = "Data Analysis"
def f(self, tens: torch.Tensor) -> tuple:
"""
Creates a pandas DataFrame from a PyTorch tensor.
Args:
tens (torch.Tensor): A PyTorch tensor.
Returns:
tuple: A tuple containing the DataFrame.
Raises:
ValueError: If the tensor is not rank 1 or rank 2.
"""
if tens.dim() not in [1, 2]:
raise ValueError("Only rank 1 and rank 2 tensors are supported.")
return (pd.DataFrame(tens.numpy()),)
@@ -5,6 +5,8 @@ import pandas as pd
class PandasHorizontalConcat:
"""
Horizontally concatenates two pandas DataFrames.
If reset labels is set to True, column labels are reset to a sequential integer index.
category: Transformation
"""
@@ -20,7 +22,8 @@ class PandasHorizontalConcat:
return {
"required": {
"a_dataframe": ("DATAFRAME", {}),
"b_dataframe": ("DATAFRAME", {})
"b_dataframe": ("DATAFRAME", {}),
"reset_labels": ("BOOLEAN", {"default": False})
}
}
@@ -28,16 +31,23 @@ class PandasHorizontalConcat:
FUNCTION: str = "f"
CATEGORY: str = "Data Analysis"
def f(self, a_dataframe: pd.DataFrame, b_dataframe: pd.DataFrame) -> tuple:
def f(self,
a_dataframe: pd.DataFrame,
b_dataframe: pd.DataFrame,
reset_labels: bool) -> tuple:
"""
Horizontally concatenate two pandas DataFrames.
Args:
a_dataframe (DataFrame): The first DataFrame.
b_dataframe (DataFrame): The second DataFrame.
reset_labels (bool): If reset labels is set to True, column labels are reset to a sequential integer index.
Returns:
tuple: A tuple containing the concatenated DataFrame.
"""
df_out = pd.concat([a_dataframe, b_dataframe], axis=1)
if reset_labels:
df_out.columns = range(df_out.shape[1])
return (df_out,)
@@ -0,0 +1,72 @@
from typing import Any, Dict
import pandas as pd
import ast
class PandasRenameAdvanced:
"""
Renames one or more indices (row labels) or column labels to new labels.
Specify the replacement in a Python dictionary format:
```
{
"old_foo": "new_bar",
0: 5
}
```
A string label has to be double-quoted.
category: Transformation
"""
@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", {}),
"axis": (("columns", "index"),),
"replacement_pairs": ("STRING", {"default":"{}", "multiline": True})
}
}
RETURN_TYPES: tuple = ("DATAFRAME",)
FUNCTION: str = "f"
CATEGORY: str = "Data Analysis"
def f(self, dataframe: pd.DataFrame, axis: str, replacement_pairs: str) -> tuple:
"""
Renames one or more indices (row labels) or column labels to new labels.
Args:
dataframe (DataFrame): The DataFrame.
axis (str): Index (row label) or column label.
replacement_pairs (str): Replacement pairs specified in the Python dictionary format.
Returns:
tuple: A tuple containing the DataFrame.
"""
try:
d = ast.literal_eval(replacement_pairs)
if not isinstance(d, dict):
raise ValueError("replacement_pairs must be a dictionary.")
# Check that values in the dictionary are not lists, tuples, or dictionaries
if any(isinstance(value, (list, tuple, dict)) for value in d.values()):
raise ValueError("replacement_pairs values must not be lists, tuples, or dictionaries.")
except (SyntaxError, ValueError) as e:
raise ValueError(f"Invalid replacement_pairs format: {e}")
if axis == "index":
df_out = dataframe.rename(index=d)
elif axis == "columns":
df_out = dataframe.rename(columns=d)
else:
raise ValueError("Invalid axis. Only 'index' or 'columns' are supported.")
return (df_out,)
+44 -2
View File
@@ -1,4 +1,4 @@
from typing import Any, List, Tuple, Union, Set
from typing import Any, List, Tuple, Union, Set, Optional
import json
import numpy as np
import pandas as pd
@@ -54,7 +54,7 @@ def column_labels_string_to_list(dataframe:pd.DataFrame, s:str, no_check:bool=Fa
Args:
dataframe (pd.DataFrame): The DataFrame to validate column names against.
s (str): A comma-separated string representing column labels.
no_check (str): If True, input string is processed as a string without checking the column labels
no_check (bool): If True, input string is processed as a string without checking the column labels
of the DataFrame.
Returns:
@@ -84,6 +84,48 @@ def column_labels_string_to_list(dataframe:pd.DataFrame, s:str, no_check:bool=Fa
return output_columns
def column_label_string_to_target_type(dataframe: pd.DataFrame, label: str, return_none: bool=False) -> Optional[Union[str, int, float]]:
"""
Converts a string column label into the data type used for the corresponding label in the DataFrame.
If a column name does not exist in the DataFrame, a ValueError is raised.
Args:
dataframe (pd.DataFrame): The DataFrame to validate column names against.
label (str): A string representing a column label.
return_none (bool): If True, if the label is not found, None is returned instead of raising an exception.
Returns:
Union[str, int, float]: The column label in the correct type used in the DataFrame.
Raises:
ValueError: If `s` does not match any existing column name.
"""
valid_columns = flatten_list_tuple_unique(dataframe.columns)
s = label.strip()
if s in valid_columns:
return s
try:
numeric_c = int(s)
if numeric_c in valid_columns:
return numeric_c
except ValueError:
pass
try:
numeric_c = float(s)
if numeric_c in valid_columns:
return numeric_c
except ValueError:
pass
if return_none:
return None
raise ValueError(f"Column '{s}' not found in the DataFrame.")
def series_to_jsons(series: pd.Series) -> str:
"""
Converts a pandas Series to a JSON string.
+2 -1
View File
@@ -6,7 +6,7 @@ from .common import common_input_types
from .util import plot_post_steps
from .util import set_up_sns_style_palette
from .util import process_y_columns_and_labels
from ..pandas_wrapper.utils import column_label_string_to_target_type
class SNSBar:
"""
@@ -63,6 +63,7 @@ class SNSBar:
"""
df = dataframe
set_up_sns_style_palette(style, palette)
x_column_name = column_label_string_to_target_type(df, x_column_name)
y_columns, labels = process_y_columns_and_labels(df, y_column_name, legend_label)
# Create the plot
+3 -1
View File
@@ -4,7 +4,7 @@ import pandas as pd
import seaborn as sns
from .util import plot_post_steps
from .util import set_up_sns_style_palette
from ..pandas_wrapper.utils import column_label_string_to_target_type
class SNSBoxplot:
"""
@@ -81,6 +81,8 @@ class SNSBoxplot:
"""
df = dataframe
set_up_sns_style_palette(style, palette)
category_column_name = column_label_string_to_target_type(df, category_column_name, return_none=True)
value_column_name = column_label_string_to_target_type(df, value_column_name)
# Create the plot
fig, ax = plt.subplots()
+2 -1
View File
@@ -6,7 +6,7 @@ from .common import common_input_types
from .util import plot_post_steps
from .util import set_up_sns_style_palette
from .util import process_y_columns_and_labels
from ..pandas_wrapper.utils import column_label_string_to_target_type
class SNSLine:
"""
@@ -83,6 +83,7 @@ class SNSLine:
"""
df = dataframe
set_up_sns_style_palette(style, palette)
x_column_name = column_label_string_to_target_type(df, x_column_name)
y_columns, labels = process_y_columns_and_labels(df, y_column_name, legend_label)
fig, ax = plt.subplots()
+2
View File
@@ -4,6 +4,7 @@ import pandas as pd
import seaborn as sns
from .util import plot_post_steps
from .util import set_up_sns_style_palette
from ..pandas_wrapper.utils import column_label_string_to_target_type
class SNSPairplot:
@@ -60,6 +61,7 @@ class SNSPairplot:
set_up_sns_style_palette(style, palette)
# Create the plot
hue_column_name = column_label_string_to_target_type(df, hue_column_name, return_none=True)
if hue_column_name:
pp = sns.pairplot(df, hue=hue_column_name)
else:
+2 -1
View File
@@ -6,7 +6,7 @@ from .common import common_input_types
from .util import plot_post_steps
from .util import set_up_sns_style_palette
from .util import process_y_columns_and_labels
from ..pandas_wrapper.utils import column_label_string_to_target_type
class SNSScatter:
"""
@@ -63,6 +63,7 @@ class SNSScatter:
"""
df = dataframe
set_up_sns_style_palette(style, palette)
x_column_name = column_label_string_to_target_type(df, x_column_name)
y_columns, labels = process_y_columns_and_labels(df, y_column_name, legend_label)
# Create the plot