Initial code commit
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
__pycache__/
|
||||
**/__pycache__/
|
||||
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
from typing import Dict, Type, TypeVar
|
||||
from .modules.matplotlib.mpl_bar import MPLBar
|
||||
from .modules.matplotlib.mpl_line import MPLLine
|
||||
from .modules.matplotlib.mpl_scatter import MPLScatter
|
||||
from .modules.pandas.pandas_head import PandasHead
|
||||
from .modules.pandas.pandas_join import PandasJoin
|
||||
from .modules.pandas.pandas_load_csv import PandasLoadCSV
|
||||
from .modules.pandas.pandas_select_columns import PandasSelectColumns
|
||||
from .modules.pandas.pandas_select_rows import PandasSelectRows
|
||||
from .modules.pandas.pandas_show_dataframe import PandasShowDataFrame
|
||||
from .modules.pandas.pandas_sort import PandasSort
|
||||
from .modules.pandas.pandas_summary import PandasSummary
|
||||
from .modules.pandas.pandas_to_string import PandasToString
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
NODE_CLASS_MAPPINGS: Dict[str, Type[T]] = {
|
||||
"MPLBar": MPLBar,
|
||||
"MPLLine": MPLLine,
|
||||
"MPLScatter": MPLScatter,
|
||||
"PandasHead": PandasHead,
|
||||
"PandasJoin": PandasJoin,
|
||||
"PandasLoadCSV": PandasLoadCSV,
|
||||
"PandasSelectColumns": PandasSelectColumns,
|
||||
"PandasSelectRows": PandasSelectRows,
|
||||
"PandasShowDataFrame": PandasShowDataFrame,
|
||||
"PandasSort": PandasSort,
|
||||
"PandasSummary": PandasSummary,
|
||||
"PandasToString": PandasToString,
|
||||
}
|
||||
"""
|
||||
NODE_CLASS_MAPPINGS (Dict[str, Type[T]]):
|
||||
A dictionary mapping node names to their corresponding class implementations.
|
||||
|
||||
- "MPLBar": Generates a bar chart from DataFrame data.
|
||||
- "MPLLine": Generates a line plot from DataFrame data.
|
||||
- "MPLScatter": Generates a scatter plot from DataFrame data.
|
||||
- "PandasHead": Handles retrieving the first few rows of a DataFrame.
|
||||
- "PandasJoin": Provides functionality to join multiple DataFrames.
|
||||
- "PandasLoadCSV": Loads CSV data into a DataFrame.
|
||||
- "PandasSelectColumns": Selects specific columns from a DataFrame.
|
||||
- "PandasSelectRows": Filters specific rows from a DataFrame.
|
||||
- "PandasShowDataFrame": Displays the content of the DataFrame.
|
||||
- "PandasSort": Sorts a DataFrame based on given criteria.
|
||||
- "PandasSummary": Provides a summary of a DataFrame.
|
||||
- "PandasToString": Converts a DataFrame to a string representation.
|
||||
"""
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS: Dict[str, str] = {
|
||||
"MPLBar": "MPL Bar Chart",
|
||||
"MPLLine": "MPL Line Plot",
|
||||
"MPLScatter": "MPL Scatter Plot",
|
||||
"PandasHead": "Pandas Head",
|
||||
"PandasJoin": "Pandas Join",
|
||||
"PandasLoadCSV": "Pandas Load CSV",
|
||||
"PandasSelectColumns": "Pandas Select Columns",
|
||||
"PandasSelectRows": "Pandas Select Rows",
|
||||
"PandasShowDataFrame": "Pandas Show DataFrame",
|
||||
"PandasSort": "Pandas Sort",
|
||||
"PandasSummary": "Pandas Summary",
|
||||
"PandasToString": "Pandas To String",
|
||||
}
|
||||
"""
|
||||
NODE_DISPLAY_NAME_MAPPINGS (Dict[str, str]):
|
||||
A dictionary mapping node names to user-friendly display names.
|
||||
"""
|
||||
|
||||
"""
|
||||
Below two lines were taken from:
|
||||
https://github.com/pythongosssss/ComfyUI-Custom-Scripts/blob/main/__init__.py
|
||||
See credit/credit.md for the full license.
|
||||
"""
|
||||
WEB_DIRECTORY = "./web"
|
||||
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS", "WEB_DIRECTORY"]
|
||||
@@ -0,0 +1,30 @@
|
||||
# Third-party license
|
||||
|
||||
## pythongosssss/ComfyUI-Custom-Scripts
|
||||
This software is licensed under the following license:
|
||||
https://github.com/pythongosssss/ComfyUI-Custom-Scripts/blob/main/LICENSE
|
||||
|
||||
Full text:
|
||||
```
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 pythongosssss
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
@@ -0,0 +1,18 @@
|
||||
def common_input_types():
|
||||
"""
|
||||
Defines the input types for a plot function.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary specifying required input types.
|
||||
"""
|
||||
return {
|
||||
"required": {
|
||||
"dataframe_json": ("STRING", {"multiscatter": True}),
|
||||
"x_column_name": ("STRING", {"default": ""}),
|
||||
"y_column_name": ("STRING", {"default": ""}),
|
||||
"title": ("STRING", {"default": ""}),
|
||||
"x_axis_label": ("STRING", {"default": ""}),
|
||||
"y_axis_label": ("STRING", {"default": ""}),
|
||||
"x_tick_as_int": ("BOOLEAN", {"default": False}) # To show 2002 instead of 2002.5 on x-axis
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
from typing import Any, Dict
|
||||
from matplotlib import pyplot as plt
|
||||
import pandas as pd
|
||||
from .common import common_input_types
|
||||
from .util import plot_post_steps
|
||||
|
||||
class MPLBar:
|
||||
"""
|
||||
MPLBar:
|
||||
A class for generating bar charts from a pandas DataFrame.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Defines the input types for the `bar_chart` function.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary specifying required input types.
|
||||
"""
|
||||
return common_input_types()
|
||||
|
||||
RETURN_TYPES: tuple = ("IMAGE",)
|
||||
FUNCTION: str = "bar_chart"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def bar_chart(self,
|
||||
dataframe_json: str,
|
||||
x_column_name: str,
|
||||
y_column_name: str,
|
||||
title: str,
|
||||
x_axis_label: str,
|
||||
y_axis_label: str,
|
||||
x_tick_as_int: bool) -> tuple:
|
||||
"""
|
||||
Generates a bar chart from a pandas DataFrame.
|
||||
|
||||
Args:
|
||||
dataframe_json (str): A JSON string representation of the DataFrame.
|
||||
x_column_name (str): The column name for the x-axis.
|
||||
y_column_name (str): The column name for the y-axis.
|
||||
title (str): The title of the plot.
|
||||
x_axis_label (str): The label for the x-axis data.
|
||||
y_axis_label (str): The label for the y-axis data.
|
||||
x_tick_as_int (bool): If set, use integers for x ticks. For example,
|
||||
if ticks show floating point numbers for years, e.g. 2002.5,
|
||||
setting this flag will show integer values instead.
|
||||
Returns:
|
||||
tuple: A tuple containing the image tensor representation of the plot.
|
||||
"""
|
||||
# Deserialize JSON string to DataFrame
|
||||
df = pd.read_json(dataframe_json)
|
||||
|
||||
# Create the plot
|
||||
fig, ax = plt.subplots()
|
||||
ax.bar(df[x_column_name], df[y_column_name])
|
||||
|
||||
return plot_post_steps(
|
||||
fig,
|
||||
ax,
|
||||
plt,
|
||||
title,
|
||||
x_axis_label,
|
||||
y_axis_label,
|
||||
x_tick_as_int)
|
||||
@@ -0,0 +1,65 @@
|
||||
from typing import Any, Dict
|
||||
from matplotlib import pyplot as plt
|
||||
import pandas as pd
|
||||
from .common import common_input_types
|
||||
from .util import plot_post_steps
|
||||
|
||||
class MPLLine:
|
||||
"""
|
||||
MPLPlotLine:
|
||||
A class for generating line plots from a pandas DataFrame.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Defines the input types for the `line_plot` function.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary specifying required input types.
|
||||
"""
|
||||
return common_input_types()
|
||||
|
||||
RETURN_TYPES: tuple = ("IMAGE",)
|
||||
FUNCTION: str = "line_plot"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def line_plot(self,
|
||||
dataframe_json: str,
|
||||
x_column_name: str,
|
||||
y_column_name: str,
|
||||
title: str,
|
||||
x_axis_label: str,
|
||||
y_axis_label: str,
|
||||
x_tick_as_int: bool) -> tuple:
|
||||
"""
|
||||
Generates a line plot from a pandas DataFrame.
|
||||
|
||||
Args:
|
||||
dataframe_json (str): A JSON string representation of the DataFrame.
|
||||
x_column_name (str): The column name for the x-axis.
|
||||
y_column_name (str): The column name for the y-axis.
|
||||
title (str): The title of the plot.
|
||||
x_axis_label (str): The label for the x-axis data.
|
||||
y_axis_label (str): The label for the y-axis data.
|
||||
x_tick_as_int (bool): If set, use integers for x ticks. For example,
|
||||
if ticks show floating point numbers for years, e.g. 2002.5,
|
||||
setting this flag will show integer values instead.
|
||||
Returns:
|
||||
tuple: A tuple containing the image tensor representation of the plot.
|
||||
"""
|
||||
# Deserialize JSON string to DataFrame
|
||||
df = pd.read_json(dataframe_json)
|
||||
|
||||
# Create the plot
|
||||
fig, ax = plt.subplots()
|
||||
ax.plot(df[x_column_name], df[y_column_name])
|
||||
|
||||
return plot_post_steps(
|
||||
fig,
|
||||
ax,
|
||||
plt,
|
||||
title,
|
||||
x_axis_label,
|
||||
y_axis_label,
|
||||
x_tick_as_int)
|
||||
@@ -0,0 +1,65 @@
|
||||
from typing import Any, Dict
|
||||
from matplotlib import pyplot as plt
|
||||
import pandas as pd
|
||||
from .common import common_input_types
|
||||
from .util import plot_post_steps
|
||||
|
||||
class MPLScatter:
|
||||
"""
|
||||
MPLPlotScatter:
|
||||
A class for generating scatter plots from a pandas DataFrame.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Defines the input types for the `scatter_plot` function.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary specifying required input types.
|
||||
"""
|
||||
return common_input_types()
|
||||
|
||||
RETURN_TYPES: tuple = ("IMAGE",)
|
||||
FUNCTION: str = "scatter_plot"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def scatter_plot(self,
|
||||
dataframe_json: str,
|
||||
x_column_name: str,
|
||||
y_column_name: str,
|
||||
title: str,
|
||||
x_axis_label: str,
|
||||
y_axis_label: str,
|
||||
x_tick_as_int: bool) -> tuple:
|
||||
"""
|
||||
Generates a scatter plot from a pandas DataFrame.
|
||||
|
||||
Args:
|
||||
dataframe_json (str): A JSON string representation of the DataFrame.
|
||||
x_column_name (str): The column name for the x-axis.
|
||||
y_column_name (str): The column name for the y-axis.
|
||||
title (str): The title of the plot.
|
||||
x_axis_label (str): The label for the x-axis data.
|
||||
y_axis_label (str): The label for the y-axis data.
|
||||
x_tick_as_int (bool): If set, use integers for x ticks. For example,
|
||||
if ticks show floating point numbers for years, e.g. 2002.5,
|
||||
setting this flag will show integer values instead.
|
||||
Returns:
|
||||
tuple: A tuple containing the image tensor representation of the plot.
|
||||
"""
|
||||
# Deserialize JSON string to DataFrame
|
||||
df = pd.read_json(dataframe_json)
|
||||
|
||||
# Create the plot
|
||||
fig, ax = plt.subplots()
|
||||
ax.plot(df[x_column_name], df[y_column_name])
|
||||
|
||||
return plot_post_steps(
|
||||
fig,
|
||||
ax,
|
||||
plt,
|
||||
title,
|
||||
x_axis_label,
|
||||
y_axis_label,
|
||||
x_tick_as_int)
|
||||
@@ -0,0 +1,56 @@
|
||||
import io
|
||||
from typing import Any, Dict
|
||||
import numpy as np
|
||||
import matplotlib.figure
|
||||
import matplotlib.axes
|
||||
from matplotlib import pyplot as plt
|
||||
import matplotlib.ticker as mticker
|
||||
import pandas as pd
|
||||
from PIL import Image
|
||||
import torch
|
||||
|
||||
|
||||
def plot_post_steps(
|
||||
fig: matplotlib.figure.Figure,
|
||||
ax: matplotlib.axes.Axes,
|
||||
plt: plt,
|
||||
title: str,
|
||||
x_axis_label: str,
|
||||
y_axis_label: str,
|
||||
x_tick_as_int: bool
|
||||
) -> tuple:
|
||||
r"""Plots a post-processed step plot using Matplotlib.
|
||||
|
||||
Args:
|
||||
fig (matplotlib.figure.Figure): The figure object for the plot.
|
||||
ax (matplotlib.axes.Axes): The axes object for the plot.
|
||||
plt (module): The Matplotlib module.
|
||||
title (str): The title of the plot.
|
||||
x_axis_label (str): The label for the x-axis.
|
||||
y_axis_label (str): The label for the y-axis.
|
||||
x_tick_as_int (bool): If ``True``, use integers for x-axis ticks.
|
||||
For example, if ticks display floating point numbers (e.g., 2002.5),
|
||||
setting this flag forces integer values instead.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing the image tensor representation of the plot.
|
||||
"""
|
||||
if x_tick_as_int:
|
||||
ax.xaxis.set_major_locator(mticker.MaxNLocator(integer=True))
|
||||
|
||||
# Set title and labels
|
||||
ax.set_title(title)
|
||||
ax.set_xlabel(x_axis_label)
|
||||
ax.set_ylabel(y_axis_label)
|
||||
|
||||
# Save the plot to a buffer
|
||||
buf = io.BytesIO()
|
||||
fig.savefig(buf, format='PNG')
|
||||
buf.seek(0)
|
||||
plt.close(fig) # Close the figure to free memory
|
||||
|
||||
# Load image and convert to tensor
|
||||
image = Image.open(buf).convert("RGB")
|
||||
image_tensor = torch.from_numpy(np.array(image)).float() / 255.0 # Normalize to [0,1]
|
||||
image_tensor = image_tensor.unsqueeze(0)
|
||||
return (image_tensor,)
|
||||
@@ -0,0 +1,44 @@
|
||||
from typing import Any, Dict
|
||||
import pandas as pd
|
||||
|
||||
|
||||
class PandasHead:
|
||||
"""
|
||||
PandasHead:
|
||||
A class for retrieving the first few rows of a pandas DataFrame.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Defines the input types for the `head` function.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary specifying required input types.
|
||||
"""
|
||||
return {
|
||||
"required": {
|
||||
"dataframe_json": ("STRING", {"multiline": True}),
|
||||
"rows": ("INT", {"default": 10, "min": 0, "max": 50})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES: tuple = ("STRING",)
|
||||
FUNCTION: str = "head"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def head(self, dataframe_json: str, rows: int) -> tuple:
|
||||
"""
|
||||
Returns the first `rows` rows of a pandas DataFrame.
|
||||
|
||||
Args:
|
||||
dataframe_json (str): A JSON string representation of the DataFrame.
|
||||
rows (int): The number of rows to retrieve.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing a JSON string of the resulting DataFrame.
|
||||
"""
|
||||
# Deserialize JSON string to DataFrame
|
||||
df = pd.read_json(dataframe_json)
|
||||
df2 = df.head(rows)
|
||||
return (df2.to_json(),)
|
||||
@@ -0,0 +1,50 @@
|
||||
from typing import Any, Dict
|
||||
import pandas as pd
|
||||
|
||||
|
||||
class PandasJoin:
|
||||
"""
|
||||
PandasJoin:
|
||||
A class for merging two pandas DataFrames based on a common column.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Defines the input types for the `sort_rows` function.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary specifying required input types.
|
||||
"""
|
||||
return {
|
||||
"required": {
|
||||
"left_dataframe_json": ("STRING", {"multiline": True}),
|
||||
"right_dataframe_json": ("STRING", {"multiline": True}),
|
||||
"on_column_name": ("STRING", {"default": ""}),
|
||||
"join_method":(("inner", "left", "right", "outer"),)
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES: tuple = ("STRING",)
|
||||
FUNCTION: str = "join_dataframes"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def join_dataframes(self, left_dataframe_json: str, right_dataframe_json: str, on_column_name: str, join_method: str) -> tuple:
|
||||
"""
|
||||
Merges two pandas DataFrames based on a common column using the specified join method.
|
||||
|
||||
Args:
|
||||
left_dataframe_json (str): A JSON string representation of the left DataFrame.
|
||||
right_dataframe_json (str): A JSON string representation of the right DataFrame.
|
||||
on_column_name (str): The name of the column to join on.
|
||||
join_method (str): The type of join to perform ("inner", "left", "right", "outer").
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing a JSON string of the merged DataFrame.
|
||||
"""
|
||||
# Deserialize JSON string to DataFrame
|
||||
df_left = pd.read_json(left_dataframe_json)
|
||||
df_right = pd.read_json(right_dataframe_json)
|
||||
|
||||
df_out = pd.merge(df_left, df_right, on=on_column_name, how=join_method)
|
||||
return (df_out.to_json(),)
|
||||
@@ -0,0 +1,45 @@
|
||||
from typing import Any, Dict
|
||||
import pandas as pd
|
||||
|
||||
|
||||
class PandasLoadCSV:
|
||||
"""
|
||||
PandasLoadCSV:
|
||||
A class for loading CSV files into a pandas DataFrame.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Defines the input types for the `load_csv` function.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary specifying required input types.
|
||||
"""
|
||||
return {
|
||||
"required": {
|
||||
"file_path": ("STRING", {"multiline": False}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES: tuple = ("STRING",)
|
||||
FUNCTION: str = "load_csv"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def load_csv(self, file_path: str) -> tuple:
|
||||
"""
|
||||
Loads a CSV file into a pandas DataFrame and converts it to a JSON string.
|
||||
|
||||
Args:
|
||||
file_path (str): The path to the CSV file.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing a JSON string representation of the DataFrame.
|
||||
"""
|
||||
# Read CSV file into DataFrame
|
||||
df = pd.read_csv(file_path)
|
||||
|
||||
# Convert DataFrame to JSON
|
||||
result_json = df.to_json()
|
||||
|
||||
return (result_json,)
|
||||
@@ -0,0 +1,47 @@
|
||||
from typing import Any, Dict
|
||||
import pandas as pd
|
||||
|
||||
class PandasSelectColumns:
|
||||
"""
|
||||
PandasSelectColumns:
|
||||
A class for selecting specific columns from a pandas DataFrame.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Defines the input types for the `select_columns` function.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary specifying required input types.
|
||||
"""
|
||||
return {
|
||||
"required": {
|
||||
"dataframe_json": ("STRING", {"multiline": True}),
|
||||
"column_names": ("STRING", {"default": ""})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES: tuple = ("STRING",)
|
||||
FUNCTION: str = "select_columns"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def select_columns(self, dataframe_json: str, column_names: str) -> tuple:
|
||||
"""
|
||||
Selects specific columns from a pandas DataFrame.
|
||||
|
||||
Args:
|
||||
dataframe_json (str): A JSON string representation of the DataFrame.
|
||||
column_names (str): A comma-separated string of column names to select.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing a JSON string of the DataFrame with selected columns.
|
||||
"""
|
||||
# Deserialize JSON string to DataFrame
|
||||
df = pd.read_json(dataframe_json)
|
||||
|
||||
# Process column names
|
||||
selected_columns = [col.strip() for col in column_names.split(",")]
|
||||
df2 = df[selected_columns]
|
||||
|
||||
return (df2.to_json(),)
|
||||
@@ -0,0 +1,47 @@
|
||||
import ast
|
||||
from typing import Any, Dict
|
||||
import pandas as pd
|
||||
|
||||
class PandasSelectRows:
|
||||
"""
|
||||
PandasSelectRows:
|
||||
A class for selecting specific rows from a pandas DataFrame based on a condition.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Defines the input types for the `select_rows` function.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary specifying required input types.
|
||||
"""
|
||||
return {
|
||||
"required": {
|
||||
"dataframe_json": ("STRING", {"multiline": True}),
|
||||
"condition": ("STRING", {"default": ""})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES: tuple = ("STRING",)
|
||||
FUNCTION: str = "select_rows"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def select_rows(self, dataframe_json: str, condition: str) -> tuple:
|
||||
"""
|
||||
Selects specific rows from a pandas DataFrame based on a given condition.
|
||||
|
||||
Args:
|
||||
dataframe_json (str): A JSON string representation of the DataFrame.
|
||||
condition (str): A string representing the condition to filter rows.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing a JSON string of the filtered DataFrame.
|
||||
"""
|
||||
# Deserialize JSON string to DataFrame
|
||||
df = pd.read_json(dataframe_json)
|
||||
|
||||
# Apply condition
|
||||
df2 = df.query(condition)
|
||||
|
||||
return (df2.to_json(),)
|
||||
@@ -0,0 +1,53 @@
|
||||
"""
|
||||
This code is based on
|
||||
https://github.com/pythongosssss/ComfyUI-Custom-Scripts/blob/main/py/show_text.py
|
||||
|
||||
See credit/credit.md for the full license.
|
||||
"""
|
||||
import pandas as pd
|
||||
|
||||
class PandasShowDataFrame:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"dataframe_json": ("STRING", {"forceInput": True}),
|
||||
},
|
||||
"hidden": {
|
||||
"unique_id": "UNIQUE_ID",
|
||||
"extra_pnginfo": "EXTRA_PNGINFO",
|
||||
},
|
||||
}
|
||||
|
||||
INPUT_IS_LIST = True
|
||||
RETURN_TYPES = ("STRING",)
|
||||
FUNCTION = "notify"
|
||||
OUTPUT_NODE = True
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
CATEGORY = "Data Analysis"
|
||||
|
||||
def notify(self, dataframe_json, unique_id=None, extra_pnginfo=None):
|
||||
text = None
|
||||
if unique_id is not None and extra_pnginfo is not None:
|
||||
if not isinstance(extra_pnginfo, list):
|
||||
print("Error: extra_pnginfo is not a list")
|
||||
elif (
|
||||
not isinstance(extra_pnginfo[0], dict)
|
||||
or "workflow" not in extra_pnginfo[0]
|
||||
):
|
||||
print("Error: extra_pnginfo[0] is not a dict or missing 'workflow' key")
|
||||
else:
|
||||
# Deserialize JSON string to DataFrame
|
||||
df = pd.read_json(dataframe_json[0])
|
||||
text = [str(df)] # wrap in list
|
||||
workflow = extra_pnginfo[0]["workflow"]
|
||||
node = next(
|
||||
(x for x in workflow["nodes"] if str(x["id"]) == str(unique_id[0])),
|
||||
None,
|
||||
)
|
||||
if node:
|
||||
node["widgets_values"] = [text]
|
||||
else:
|
||||
print("unique_id or extra_pnginfo is None.")
|
||||
return {"ui": {"text": text}, "result": (text,)}
|
||||
@@ -0,0 +1,48 @@
|
||||
from typing import Any, Dict
|
||||
import pandas as pd
|
||||
|
||||
class PandasSort:
|
||||
"""
|
||||
PandasSort:
|
||||
A class for sorting a pandas DataFrame by a specified column.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Defines the input types for the `sort_rows` function.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary specifying required input types.
|
||||
"""
|
||||
return {
|
||||
"required": {
|
||||
"dataframe_json": ("STRING", {"multiline": True}),
|
||||
"column_name": ("STRING", {"default": ""}),
|
||||
"ascending": ("BOOLEAN", {"default": True})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES: tuple = ("STRING",)
|
||||
FUNCTION: str = "sort_rows"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def sort_rows(self, dataframe_json: str, column_name: str, ascending: bool) -> tuple:
|
||||
"""
|
||||
Sorts a pandas DataFrame by the specified column.
|
||||
|
||||
Args:
|
||||
dataframe_json (str): A JSON string representation of the DataFrame.
|
||||
column_name (str): The name of the column to sort by.
|
||||
ascending (bool): Whether to sort in ascending order.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing a JSON string of the sorted DataFrame.
|
||||
"""
|
||||
# Deserialize JSON string to DataFrame
|
||||
df = pd.read_json(dataframe_json)
|
||||
|
||||
# Sort DataFrame
|
||||
df2 = df.sort_values(by=column_name, ascending=ascending)
|
||||
|
||||
return (df2.to_json(),)
|
||||
@@ -0,0 +1,44 @@
|
||||
from typing import Any, Dict
|
||||
import pandas as pd
|
||||
|
||||
class PandasSummary:
|
||||
"""
|
||||
PandasSummary:
|
||||
A class for analyzing and summarizing a pandas DataFrame.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Defines the input types for the `analyze_dataframe` function.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary specifying required input types.
|
||||
"""
|
||||
return {
|
||||
"required": {
|
||||
"dataframe_json": ("STRING", {"multiline": True}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES: tuple = ("STRING",)
|
||||
FUNCTION: str = "analyze_dataframe"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def analyze_dataframe(self, dataframe_json: str) -> tuple:
|
||||
"""
|
||||
Analyzes a pandas DataFrame and returns a summary.
|
||||
|
||||
Args:
|
||||
dataframe_json (str): A JSON string representation of the DataFrame.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing a string representation of the DataFrame summary.
|
||||
"""
|
||||
# Deserialize JSON string to DataFrame
|
||||
df = pd.read_json(dataframe_json)
|
||||
|
||||
# Perform summary operation
|
||||
summary = df.describe()
|
||||
|
||||
return (str(summary),)
|
||||
@@ -0,0 +1,40 @@
|
||||
from typing import Any, Dict
|
||||
import pandas as pd
|
||||
|
||||
class PandasToString:
|
||||
"""
|
||||
PandasToString:
|
||||
A class for converting a pandas DataFrame to a string representation.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> Dict[str, Any]:
|
||||
"""
|
||||
Defines the input types for the `to_string` function.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: A dictionary specifying required input types.
|
||||
"""
|
||||
return {
|
||||
"required": {
|
||||
"dataframe_json": ("STRING", {"multiline": True}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES: tuple = ("STRING",)
|
||||
FUNCTION: str = "to_string"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def to_string(self, dataframe_json: str) -> tuple:
|
||||
"""
|
||||
Converts a pandas DataFrame to a string representation.
|
||||
|
||||
Args:
|
||||
dataframe_json (str): A JSON string representation of the DataFrame.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing the string representation of the DataFrame.
|
||||
"""
|
||||
# Deserialize JSON string to DataFrame
|
||||
df = pd.read_json(dataframe_json)
|
||||
return (str(df),)
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
This code is based on
|
||||
https://github.com/pythongosssss/ComfyUI-Custom-Scripts/blob/main/web/js/showText.js
|
||||
|
||||
See credit/credit.md for the full license.
|
||||
*/
|
||||
|
||||
import { app } from "../../../scripts/app.js";
|
||||
import { ComfyWidgets } from "../../../scripts/widgets.js";
|
||||
|
||||
// Displays input text on a node
|
||||
app.registerExtension({
|
||||
name: "HowToSD.ShowDataFrame",
|
||||
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
||||
if (nodeData.name === "PandasShowDataFrame") { // This needs to match NODE_CLASS_MAPPINGS in Python
|
||||
function populate(text) {
|
||||
if (this.widgets) {
|
||||
for (let i = 1; i < this.widgets.length; i++) {
|
||||
this.widgets[i].onRemove?.();
|
||||
}
|
||||
this.widgets.length = 1;
|
||||
}
|
||||
|
||||
const v = [...text];
|
||||
if (!v[0]) {
|
||||
v.shift();
|
||||
}
|
||||
for (const list of v) {
|
||||
const w = ComfyWidgets["STRING"](this, "text2", ["STRING", { multiline: true }], app).widget;
|
||||
w.inputEl.readOnly = true;
|
||||
w.inputEl.style.opacity = 0.6;
|
||||
w.value = list;
|
||||
}
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
const sz = this.computeSize();
|
||||
if (sz[0] < this.size[0]) {
|
||||
sz[0] = this.size[0];
|
||||
}
|
||||
if (sz[1] < this.size[1]) {
|
||||
sz[1] = this.size[1];
|
||||
}
|
||||
this.onResize?.(sz);
|
||||
app.graph.setDirtyCanvas(true, false);
|
||||
});
|
||||
}
|
||||
|
||||
// When the node is executed we will be sent the input text, display this in the widget
|
||||
const onExecuted = nodeType.prototype.onExecuted;
|
||||
nodeType.prototype.onExecuted = function (message) {
|
||||
onExecuted?.apply(this, arguments);
|
||||
populate.call(this, message.text);
|
||||
};
|
||||
|
||||
const onConfigure = nodeType.prototype.onConfigure;
|
||||
nodeType.prototype.onConfigure = function () {
|
||||
onConfigure?.apply(this, arguments);
|
||||
if (this.widgets_values?.length) {
|
||||
populate.call(this, this.widgets_values.slice(+this.widgets_values.length > 1));
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user