Added Pandas To Datetime and Pandas Strftime nodes.
This commit is contained in:
@@ -87,6 +87,7 @@ from .modules.pandas_wrapper.pandas_sin import PandasSin
|
||||
from .modules.pandas_wrapper.pandas_skew import PandasSkew
|
||||
from .modules.pandas_wrapper.pandas_sort import PandasSort
|
||||
from .modules.pandas_wrapper.pandas_std import PandasStd
|
||||
from .modules.pandas_wrapper.pandas_strftime import PandasStrftime
|
||||
from .modules.pandas_wrapper.pandas_sub import PandasSub
|
||||
from .modules.pandas_wrapper.pandas_sub_scalar_float import PandasSubScalarFloat
|
||||
from .modules.pandas_wrapper.pandas_sub_scalar_int import PandasSubScalarInt
|
||||
@@ -94,6 +95,7 @@ from .modules.pandas_wrapper.pandas_sub_series import PandasSubSeries
|
||||
from .modules.pandas_wrapper.pandas_sum import PandasSum
|
||||
from .modules.pandas_wrapper.pandas_summary import PandasSummary
|
||||
from .modules.pandas_wrapper.pandas_tan import PandasTan
|
||||
from .modules.pandas_wrapper.pandas_to_datetime import PandasToDatetime
|
||||
from .modules.pandas_wrapper.pandas_to_string import PandasToString
|
||||
from .modules.pandas_wrapper.pandas_transpose import PandasTranspose
|
||||
from .modules.pandas_wrapper.pandas_var import PandasVar
|
||||
@@ -196,6 +198,7 @@ NODE_CLASS_MAPPINGS: Dict[str, Type[T]] = {
|
||||
"PandasSkew": PandasSkew,
|
||||
"PandasSort": PandasSort,
|
||||
"PandasStd": PandasStd,
|
||||
"PandasStrftime": PandasStrftime,
|
||||
"PandasSub": PandasSub,
|
||||
"PandasSubScalarFloat": PandasSubScalarFloat,
|
||||
"PandasSubScalarInt": PandasSubScalarInt,
|
||||
@@ -203,6 +206,7 @@ NODE_CLASS_MAPPINGS: Dict[str, Type[T]] = {
|
||||
"PandasSum": PandasSum,
|
||||
"PandasSummary": PandasSummary,
|
||||
"PandasTan": PandasTan,
|
||||
"PandasToDatetime": PandasToDatetime,
|
||||
"PandasToString": PandasToString,
|
||||
"PandasTranspose": PandasTranspose,
|
||||
"PandasVar": PandasVar,
|
||||
@@ -305,6 +309,7 @@ NODE_DISPLAY_NAME_MAPPINGS: Dict[str, str] = {
|
||||
"PandasSkew": "Pandas Skew",
|
||||
"PandasSort": "Pandas Sort",
|
||||
"PandasStd": "Pandas Std",
|
||||
"PandasStrftime": "Pandas Strftime",
|
||||
"PandasSub": "Pandas Sub",
|
||||
"PandasSubScalarFloat": "Pandas Sub Scalar Float",
|
||||
"PandasSubScalarInt": "Pandas Sub Scalar Int",
|
||||
@@ -312,6 +317,7 @@ NODE_DISPLAY_NAME_MAPPINGS: Dict[str, str] = {
|
||||
"PandasSum": "Pandas Sum",
|
||||
"PandasSummary": "Pandas Summary",
|
||||
"PandasTan": "Pandas Tan",
|
||||
"PandasToDatetime": "Pandas To Datetime",
|
||||
"PandasToString": "Pandas To String",
|
||||
"PandasTranspose": "Pandas Transpose",
|
||||
"PandasVar": "Pandas Var",
|
||||
|
||||
@@ -65,6 +65,11 @@
|
||||
| --- | --- |
|
||||
| [Pandas Columns](pandas_columns.md) | Retrieves the column labels of a pandas DataFrame. |
|
||||
| [Pandas Index](pandas_index.md) | Retrieves the row labels (index) of a pandas DataFrame. |
|
||||
## Date and time processing
|
||||
| Node | Description |
|
||||
| --- | --- |
|
||||
| [Pandas Strftime](pandas_strftime.md) | Converts one or more datetime columns in a DataFrame to string columns. |
|
||||
| [Pandas To Datetime](pandas_to_datetime.md) | Converts one or more string columns in a DataFrame to datetime columns. |
|
||||
## Display data
|
||||
| Node | Description |
|
||||
| --- | --- |
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# Pandas Strftime
|
||||
Converts one or more datetime columns in a DataFrame to string columns.
|
||||
|
||||
Refer to [https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior](Python document) for date/time format strings.
|
||||
|
||||
## Input
|
||||
| Name | Data type |
|
||||
|---|---|
|
||||
| dataframe | DataFrame |
|
||||
| column_names | String |
|
||||
| date_format | String |
|
||||
|
||||
## Output
|
||||
| Data type |
|
||||
|---|
|
||||
| DataFrame |
|
||||
|
||||
<HR>
|
||||
Category: Date and time processing
|
||||
|
||||
ComfyUI Data Analysis Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
|
||||
@@ -0,0 +1,22 @@
|
||||
# Pandas To Datetime
|
||||
Converts one or more string columns in a DataFrame to datetime columns.
|
||||
|
||||
Note: When only the time portion is provided, the date defaults to 1900-01-01.
|
||||
Refer to [https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior](the Python documentation) for valid date/time format strings.
|
||||
|
||||
## Input
|
||||
| Name | Data type |
|
||||
|---|---|
|
||||
| dataframe | DataFrame |
|
||||
| column_names | String |
|
||||
| date_format | String |
|
||||
|
||||
## Output
|
||||
| Data type |
|
||||
|---|
|
||||
| DataFrame |
|
||||
|
||||
<HR>
|
||||
Category: Date and time processing
|
||||
|
||||
ComfyUI Data Analysis Node Reference. © 2025 Hide Inada (HowToSD.com). All rights reserved.
|
||||
@@ -0,0 +1,55 @@
|
||||
from typing import Any, Dict
|
||||
import pandas as pd
|
||||
import pandas.api.types as ptypes
|
||||
|
||||
|
||||
class PandasStrftime:
|
||||
"""
|
||||
Converts one or more datetime columns in a DataFrame to string columns.
|
||||
|
||||
Refer to [https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior](Python document) for date/time format strings.
|
||||
|
||||
category: Date and time processing
|
||||
"""
|
||||
|
||||
@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", {}),
|
||||
"column_names": ("STRING", {"default": ""}),
|
||||
"date_format": ("STRING", {"default": ""}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES: tuple = ("DATAFRAME",)
|
||||
FUNCTION: str = "f"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def f(self, dataframe: pd.DataFrame, column_names: str, date_format: str) -> tuple:
|
||||
"""
|
||||
Converts one or more datetime columns in a DataFrame to string columns.
|
||||
|
||||
Args:
|
||||
dataframe (DataFrame): The DataFrame.
|
||||
column_names (str): A comma-separated string of column names containing datetime values.
|
||||
date_format (str): A date format string for strftime.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing the DataFrame with formatted date columns.
|
||||
"""
|
||||
date_columns = [col.strip() for col in column_names.split(",")]
|
||||
|
||||
df2 = dataframe.copy()
|
||||
df2[date_columns] = df2[date_columns].apply(
|
||||
# Keep the datetime column check in case the user specifies the non-date column
|
||||
lambda col: col.dt.strftime(date_format) if ptypes.is_datetime64_any_dtype(col) else col
|
||||
)
|
||||
|
||||
return (df2,)
|
||||
@@ -0,0 +1,50 @@
|
||||
from typing import Any, Dict
|
||||
import pandas as pd
|
||||
import pandas.api.types as ptypes
|
||||
|
||||
|
||||
class PandasToDatetime:
|
||||
"""
|
||||
Converts one or more string columns in a DataFrame to datetime columns.
|
||||
|
||||
Note: When only the time portion is provided, the date defaults to 1900-01-01.
|
||||
Refer to [https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior](the Python documentation) for valid date/time format strings.
|
||||
|
||||
category: Date and time processing
|
||||
"""
|
||||
|
||||
@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", {}),
|
||||
"column_names": ("STRING", {"default": ""}),
|
||||
"date_format": ("STRING", {"default": ""}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES: tuple = ("DATAFRAME",)
|
||||
FUNCTION: str = "f"
|
||||
CATEGORY: str = "Data Analysis"
|
||||
|
||||
def f(self, dataframe: pd.DataFrame, column_names: str, date_format: str) -> tuple:
|
||||
"""
|
||||
Converts one or more string columns to datetime columns.
|
||||
|
||||
Args:
|
||||
dataframe (DataFrame): The DataFrame.
|
||||
column_names (str): A comma-separated string of column names containing date time strings.
|
||||
date_format (str): A date format.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing the DataFrame with selected columns.
|
||||
"""
|
||||
date_columns = [col.strip() for col in column_names.split(",")]
|
||||
df2 = dataframe.apply(lambda col: pd.to_datetime(col, format=date_format) if col.name in date_columns else col)
|
||||
return (df2,)
|
||||
+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.20"
|
||||
version = "1.1.21"
|
||||
license = {file = "LICENSE"}
|
||||
|
||||
[project.urls]
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
import pandas as pd
|
||||
import pandas.api.types as ptypes
|
||||
|
||||
PROJECT_ROOT = os.path.realpath(os.path.join(__file__, "..", "..", ".."))
|
||||
MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules")
|
||||
sys.path.append(MODULE_ROOT)
|
||||
print(MODULE_ROOT)
|
||||
|
||||
from pandas_wrapper.pandas_to_datetime import PandasToDatetime
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
def setUp(self):
|
||||
"""Set up test data"""
|
||||
self.node = PandasToDatetime()
|
||||
self.pd_date = pd.DataFrame({
|
||||
"A": ["2015-01-23", "2013-06-30"],
|
||||
"B": ["2005-02-24", "2015-09-06"],
|
||||
"C": [123.45, 987.65],
|
||||
})
|
||||
|
||||
self.pd_date_time = pd.DataFrame({
|
||||
"A": ["2015-01-23 00:12:34", "2013-06-30 12:50:59"],
|
||||
"B": [123.45, 987.65],
|
||||
})
|
||||
|
||||
self.pd_time = pd.DataFrame({
|
||||
"A": ["00:12:34", "12:50:59"],
|
||||
"B": [123.45, 987.65],
|
||||
})
|
||||
|
||||
def test_date(self):
|
||||
"""Test"""
|
||||
df2 = self.node.f(self.pd_date, column_names="A,B", date_format="%Y-%m-%d")[0]
|
||||
self.assertEqual(df2.at[0, "A"], pd.Timestamp("2015-01-23"))
|
||||
self.assertEqual(df2.at[0, "C"], 123.45)
|
||||
|
||||
def test_date_time(self):
|
||||
"""Test"""
|
||||
df3 = self.node.f(self.pd_date_time, column_names="A", date_format="%Y-%m-%d %H:%M:%S")[0]
|
||||
self.assertTrue(ptypes.is_datetime64_any_dtype(df3["A"]))
|
||||
self.assertTrue(ptypes.is_float_dtype(df3["B"]))
|
||||
self.assertEqual(df3.at[0, "A"], pd.Timestamp("2015-01-23 00:12:34"))
|
||||
self.assertEqual(df3.at[0, "B"], 123.45)
|
||||
|
||||
def test_time(self):
|
||||
"""Test"""
|
||||
df3 = self.node.f(self.pd_time, column_names="A", date_format="%H:%M:%S")[0]
|
||||
self.assertTrue(ptypes.is_datetime64_any_dtype(df3["A"]))
|
||||
self.assertEqual(df3.at[0, "A"], pd.Timestamp("1900-01-01 00:12:34"))
|
||||
self.assertEqual(df3.at[0, "B"], 123.45)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,63 @@
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
import pandas as pd
|
||||
import pandas.api.types as ptypes
|
||||
|
||||
PROJECT_ROOT = os.path.realpath(os.path.join(__file__, "..", "..", ".."))
|
||||
MODULE_ROOT = os.path.join(PROJECT_ROOT, "modules")
|
||||
sys.path.append(MODULE_ROOT)
|
||||
print(MODULE_ROOT)
|
||||
|
||||
from pandas_wrapper.pandas_strftime import PandasStrftime
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
def setUp(self):
|
||||
"""Set up test data"""
|
||||
self.node = PandasStrftime()
|
||||
|
||||
self.pd_date = pd.DataFrame({
|
||||
"A": [pd.Timestamp("2015-01-23"), pd.Timestamp("2013-06-30")],
|
||||
"B": [pd.Timestamp("2005-02-24"), pd.Timestamp("2015-09-06")],
|
||||
"C": [123.45, 987.65],
|
||||
})
|
||||
|
||||
self.pd_date_time = pd.DataFrame({
|
||||
"A": [pd.Timestamp("2015-01-23 00:12:34"), pd.Timestamp("2013-06-30 12:50:59")],
|
||||
"B": [123.45, 987.65],
|
||||
})
|
||||
|
||||
self.pd_time = pd.DataFrame({
|
||||
"A": [pd.Timestamp("1900-01-01 00:12:34"), pd.Timestamp("1900-01-01 12:50:59")],
|
||||
"B": [123.45, 987.65],
|
||||
})
|
||||
|
||||
def test_date(self):
|
||||
"""Test date formatting"""
|
||||
df2 = self.node.f(self.pd_date, column_names="A,B", date_format="%Y-%m-%d")[0]
|
||||
self.assertTrue(ptypes.is_string_dtype(df2["A"]))
|
||||
self.assertTrue(ptypes.is_string_dtype(df2["B"]))
|
||||
self.assertEqual(df2.at[0, "A"], "2015-01-23")
|
||||
self.assertEqual(df2.at[1, "B"], "2015-09-06")
|
||||
self.assertEqual(df2.at[0, "C"], 123.45) # Ensure non-date columns are unchanged
|
||||
|
||||
def test_date_time(self):
|
||||
"""Test datetime formatting"""
|
||||
df3 = self.node.f(self.pd_date_time, column_names="A", date_format="%Y-%m-%d %H:%M:%S")[0]
|
||||
self.assertTrue(ptypes.is_string_dtype(df3["A"]))
|
||||
self.assertTrue(ptypes.is_float_dtype(df3["B"]))
|
||||
self.assertEqual(df3.at[0, "A"], "2015-01-23 00:12:34")
|
||||
self.assertEqual(df3.at[1, "A"], "2013-06-30 12:50:59")
|
||||
self.assertEqual(df3.at[0, "B"], 123.45)
|
||||
|
||||
def test_time(self):
|
||||
"""Test time formatting"""
|
||||
df4 = self.node.f(self.pd_time, column_names="A", date_format="%H:%M:%S")[0]
|
||||
self.assertTrue(ptypes.is_string_dtype(df4["A"]))
|
||||
self.assertEqual(df4.at[0, "A"], "00:12:34")
|
||||
self.assertEqual(df4.at[1, "A"], "12:50:59")
|
||||
self.assertEqual(df4.at[0, "B"], 123.45)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user