Added Pandas Save CSV node
This commit is contained in:
@@ -7,7 +7,8 @@ ComfyUI-Data-Analysis is a custom module for analyzing data using Pandas and Mat
|
||||
|
||||
Currently, it supports the following nodes:
|
||||
|
||||
- Loading CSV as a DataFrame
|
||||
- Loading a CSV file as a DataFrame
|
||||
- Saving a DataFrame to a CSV file
|
||||
- Selecting a subset of columns from a DataFrame
|
||||
- Selecting a subset of rows from a DataFrame by specifying a filter condition
|
||||
- Sorting a DataFrame by a column
|
||||
|
||||
@@ -5,6 +5,7 @@ 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_save_csv import PandasSaveCSV
|
||||
from .modules.pandas.pandas_select_columns import PandasSelectColumns
|
||||
from .modules.pandas.pandas_select_rows import PandasSelectRows
|
||||
from .modules.pandas.pandas_show_dataframe import PandasShowDataFrame
|
||||
@@ -21,6 +22,7 @@ NODE_CLASS_MAPPINGS: Dict[str, Type[T]] = {
|
||||
"PandasHead": PandasHead,
|
||||
"PandasJoin": PandasJoin,
|
||||
"PandasLoadCSV": PandasLoadCSV,
|
||||
"PandasSaveCSV": PandasSaveCSV,
|
||||
"PandasSelectColumns": PandasSelectColumns,
|
||||
"PandasSelectRows": PandasSelectRows,
|
||||
"PandasShowDataFrame": PandasShowDataFrame,
|
||||
@@ -38,6 +40,7 @@ NODE_CLASS_MAPPINGS (Dict[str, Type[T]]):
|
||||
- "PandasHead": Handles retrieving the first few rows of a DataFrame.
|
||||
- "PandasJoin": Provides functionality to join multiple DataFrames.
|
||||
- "PandasLoadCSV": Loads CSV data into a DataFrame.
|
||||
- "PandasSaveCSV": Save a DataFrame to a CSV file.
|
||||
- "PandasSelectColumns": Selects specific columns from a DataFrame.
|
||||
- "PandasSelectRows": Filters specific rows from a DataFrame.
|
||||
- "PandasShowDataFrame": Displays the content of the DataFrame.
|
||||
@@ -53,6 +56,7 @@ NODE_DISPLAY_NAME_MAPPINGS: Dict[str, str] = {
|
||||
"PandasHead": "Pandas Head",
|
||||
"PandasJoin": "Pandas Join",
|
||||
"PandasLoadCSV": "Pandas Load CSV",
|
||||
"PandasSaveCSV": "Pandas Save CSV",
|
||||
"PandasSelectColumns": "Pandas Select Columns",
|
||||
"PandasSelectRows": "Pandas Select Rows",
|
||||
"PandasShowDataFrame": "Pandas Show DataFrame",
|
||||
|
||||
@@ -35,6 +35,9 @@ Use **Pandas Load CSV** node to load a CSV.
|
||||
This will emit the DataFrame in a JSON string.
|
||||
CSV file path is relative to the ComfyUI installation directory unless you specify the absolute file path.
|
||||
|
||||
## Saving data
|
||||
Use **Pandas Save CSV** node to save the DataFrame to a CSV file.
|
||||
|
||||
## Selecting columns and rows
|
||||
Use **Pandas Select Columns** for selecting columns, **Pandas Select Rows** to select rows by a filter condition.
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
from typing import Any, Dict
|
||||
from io import StringIO
|
||||
import pandas as pd
|
||||
|
||||
class PandasSaveCSV:
|
||||
"""
|
||||
PandasSaveCSV:
|
||||
A class for saving a PandasDataFrame to a CSV file.
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"dataframe_json": ("STRING", {"forceInput": True}),
|
||||
"file_path": ("STRING", {"multiline": False})
|
||||
},
|
||||
"hidden": {
|
||||
"unique_id": "UNIQUE_ID",
|
||||
"extra_pnginfo": "EXTRA_PNGINFO",
|
||||
},
|
||||
}
|
||||
|
||||
INPUT_IS_LIST = True
|
||||
RETURN_TYPES = ("STRING",)
|
||||
FUNCTION = "save_csv"
|
||||
OUTPUT_NODE = True
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
|
||||
CATEGORY = "Data Analysis"
|
||||
|
||||
def save_csv(self, dataframe_json,file_path=None, 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")
|
||||
elif file_path is None or len(file_path) == 0:
|
||||
print("Error: file path is not specified")
|
||||
else:
|
||||
# Deserialize JSON string to DataFrame
|
||||
df = pd.read_json(StringIO(dataframe_json[0]))
|
||||
df.to_csv(path_or_buf=file_path[0]) # Save as CSV
|
||||
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,)}
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "data-analysis"
|
||||
description = "Data analysis custom modules for ComfyUI - Use Pandas & Matplotlib within ComfyUI"
|
||||
version = "1.0.4"
|
||||
version = "1.0.5"
|
||||
license = {file = "LICENSE"}
|
||||
|
||||
[project.urls]
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
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.SaveCSV",
|
||||
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
||||
if (nodeData.name === "PandasSaveCSV") { // This needs to match NODE_CLASS_MAPPINGS in Python
|
||||
function populate(text) {
|
||||
// No op as we are not updating the node's UI for now.
|
||||
}
|
||||
|
||||
// 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