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
@@ -0,0 +1,54 @@
import os
import sys
import unittest
import torch
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_tensor import PandasCreateFromTensor
class TestPandasCreateFromTensor(unittest.TestCase):
def setUp(self):
"""Set up test data."""
self.node = PandasCreateFromTensor()
self.test_cases = [
# Rank 0 (Invalid)
(torch.tensor(42), ValueError),
(torch.tensor(3.14), ValueError),
(torch.tensor(True), ValueError),
# Rank 1 (Valid)
(torch.tensor([1, 2, 3], dtype=torch.float32), pd.DataFrame([1, 2, 3], dtype="float32")),
(torch.tensor([1.1, 2.2, 3.3], dtype=torch.float32), pd.DataFrame([1.1, 2.2, 3.3], dtype="float32")),
(torch.tensor([True, False, True], dtype=torch.float32), pd.DataFrame([1.0, 0.0, 1.0], dtype="float32")),
# Rank 2 (Valid)
(torch.tensor([[1, 2], [3, 4]], dtype=torch.float32), pd.DataFrame([[1, 2], [3, 4]], dtype="float32")),
(torch.tensor([[1.1, 2.2], [3.3, 4.4]], dtype=torch.float32), pd.DataFrame([[1.1, 2.2], [3.3, 4.4]], dtype="float32")),
# Rank 3+ (Invalid)
(torch.rand(2, 2, 2), ValueError),
(torch.rand(2, 2, 2, 2), ValueError),
]
def test_create_dataframe(self):
"""Test DataFrame creation from various PyTorch tensors."""
for data, expected in self.test_cases:
with self.subTest(data=data):
if isinstance(expected, type) and issubclass(expected, Exception):
with self.assertRaises(expected):
self.node.f(data)
else:
retval = self.node.f(data)[0]
# Test if DataFrame structure matches
self.assertTrue(isinstance(retval, pd.DataFrame))
# Test if data matches
pd.testing.assert_frame_equal(retval, expected)
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,48 @@
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_horizontal_concat import PandasHorizontalConcat
class TestPandasHorizontalConcat(unittest.TestCase):
def setUp(self):
"""Set up test data."""
self.node = PandasHorizontalConcat()
# Sample DataFrames
self.df1 = pd.DataFrame({"A": [1, 2], "B": [3, 4]})
self.df2 = pd.DataFrame({"C": [5, 6], "D": [7, 8]})
def test_concat_without_reset_labels(self):
"""Test horizontal concatenation without resetting column labels."""
expected_df = pd.DataFrame({
"A": [1, 2],
"B": [3, 4],
"C": [5, 6],
"D": [7, 8]
})
retval = self.node.f(self.df1, self.df2, reset_labels=False)[0]
pd.testing.assert_frame_equal(retval, expected_df)
def test_concat_with_reset_labels(self):
"""Test horizontal concatenation with resetting column labels."""
expected_df = pd.DataFrame({
0: [1, 2],
1: [3, 4],
2: [5, 6],
3: [7, 8]
})
retval = self.node.f(self.df1, self.df2, reset_labels=True)[0]
pd.testing.assert_frame_equal(retval, expected_df)
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,107 @@
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_rename_advanced import PandasRenameAdvanced
class TestPandasRenameAdvanced(unittest.TestCase):
def setUp(self):
"""Set up test data."""
self.node = PandasRenameAdvanced()
# Sample DataFrame
self.df = pd.DataFrame(
{
"A": [1, 2, 3],
"B": [4, 5, 6],
100: [7, 8, 9],
},
index=["row1", "row2", 10]
)
def test_rename_columns_string(self):
"""Test renaming string column labels."""
replacement_pairs = '{"A": "X", "B": "Y"}'
expected_df = pd.DataFrame(
{
"X": [1, 2, 3],
"Y": [4, 5, 6],
100: [7, 8, 9],
},
index=["row1", "row2", 10]
)
result_df = self.node.f(self.df, "columns", replacement_pairs)[0]
pd.testing.assert_frame_equal(result_df, expected_df)
def test_rename_columns_integer(self):
"""Test renaming integer column labels."""
replacement_pairs = '{100: 200}'
expected_df = pd.DataFrame(
{
"A": [1, 2, 3],
"B": [4, 5, 6],
200: [7, 8, 9],
},
index=["row1", "row2", 10]
)
result_df = self.node.f(self.df, "columns", replacement_pairs)[0]
pd.testing.assert_frame_equal(result_df, expected_df)
def test_rename_index_string(self):
"""Test renaming string row labels."""
replacement_pairs = '{"row1": "new_row1", "row2": "new_row2"}'
expected_df = pd.DataFrame(
{
"A": [1, 2, 3],
"B": [4, 5, 6],
100: [7, 8, 9],
},
index=["new_row1", "new_row2", 10]
)
result_df = self.node.f(self.df, "index", replacement_pairs)[0]
pd.testing.assert_frame_equal(result_df, expected_df)
def test_rename_index_integer(self):
"""Test renaming integer row labels."""
replacement_pairs = '{10: 20}'
expected_df = pd.DataFrame(
{
"A": [1, 2, 3],
"B": [4, 5, 6],
100: [7, 8, 9],
},
index=["row1", "row2", 20]
)
result_df = self.node.f(self.df, "index", replacement_pairs)[0]
pd.testing.assert_frame_equal(result_df, expected_df)
def test_invalid_replacement_pairs_list(self):
"""Test invalid replacement_pairs format."""
invalid_pairs = '{"A": ["X", "Y"]}' # Not a valid mapping. List is not allowed.
with self.assertRaises(ValueError):
self.node.f(self.df, "columns", invalid_pairs)
def test_invalid_replacement_pairs_dict(self):
"""Test invalid replacement_pairs format."""
invalid_pairs = '{"A": {"X": "Y"}}'
with self.assertRaises(ValueError):
self.node.f(self.df, "columns", invalid_pairs)
def test_invalid_replacement_pairs_tuple(self):
"""Test invalid replacement_pairs format."""
invalid_pairs = '{"A": ()"X", "Y")}'
with self.assertRaises(ValueError):
self.node.f(self.df, "columns", invalid_pairs)
def test_invalid_axis(self):
"""Test invalid axis value."""
replacement_pairs = '{"A": "X"}'
with self.assertRaises(ValueError):
self.node.f(self.df, "invalid_axis", replacement_pairs)
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,61 @@
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.utils import column_label_string_to_target_type
class TestColumnLabelStringToTargetType(unittest.TestCase):
def setUp(self):
"""Set up test data."""
self.df = pd.DataFrame({
"A": [1, 2, 3],
"B": [4, 5, 6],
"C": [7, 8, 9],
10: [10, 11, 12], # Integer column name
20: [13, 14, 15], # Another integer column name
3.5: [16, 17, 18] # Float column name
})
def test_valid_string_column(self):
"""Test valid string column names remain unchanged."""
self.assertEqual(column_label_string_to_target_type(self.df, "A"), "A")
self.assertEqual(column_label_string_to_target_type(self.df, "B"), "B")
def test_integer_column_labels(self):
"""Test conversion when integer column names are referenced as strings."""
self.assertEqual(column_label_string_to_target_type(self.df, "10"), 10)
self.assertEqual(column_label_string_to_target_type(self.df, "20"), 20)
def test_float_column_label(self):
"""Test conversion when float column names are referenced as strings."""
self.assertEqual(column_label_string_to_target_type(self.df, "3.5"), 3.5)
def test_whitespace_handling(self):
"""Test that spaces around column names are stripped before conversion."""
self.assertEqual(column_label_string_to_target_type(self.df, " A "), "A")
self.assertEqual(column_label_string_to_target_type(self.df, " 10 "), 10)
self.assertEqual(column_label_string_to_target_type(self.df, " 3.5 "), 3.5)
def test_non_existent_column(self):
"""Test behavior when a non-existent column is provided."""
with self.assertRaises(ValueError) as context:
column_label_string_to_target_type(self.df, "D")
self.assertIn("Column 'D' not found in the DataFrame.", str(context.exception))
def test_non_existent_column_with_return_none(self):
"""Test behavior when a non-existent column is provided."""
retval = column_label_string_to_target_type(self.df, "D", return_none=True)
self.assertTrue(retval is None)
def test_invalid_integer_conversion(self):
"""Test that a string that can't be converted to an integer or float raises ValueError."""
with self.assertRaises(ValueError) as context:
column_label_string_to_target_type(self.df, "xyz")
self.assertIn("Column 'xyz' not found in the DataFrame.", str(context.exception))
if __name__ == "__main__":
unittest.main()