Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Added Table.transform_table method which returns the transformed Table #229

Merged
merged 8 commits into from
Apr 21, 2023
38 changes: 36 additions & 2 deletions src/safeds/data/tabular/containers/_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
if TYPE_CHECKING:
from collections.abc import Callable, Iterable

from safeds.data.tabular.transformation import InvertibleTableTransformer
from safeds.data.tabular.transformation import InvertibleTableTransformer, TableTransformer

from ._tagged_table import TaggedTable

Expand Down Expand Up @@ -993,6 +993,40 @@ def transform_column(self, name: str, transformer: Callable[[Row], Any]) -> Tabl
return self.replace_column(name, result)
raise UnknownColumnNameError([name])

def transform_table(self, transformer: TableTransformer) -> Table:
"""
Apply a learned transformation onto this table.

Parameters
----------
transformer : TableTransformer
The transformer which transforms the given table.

Returns
-------
transformed_table : Table
The transformed table.

Raises
------
TransformerNotFittedError
If the transformer has not been fitted yet.

Examples
--------
>>> from safeds.data.tabular.transformation import OneHotEncoder
>>> from safeds.data.tabular.containers import Table
>>> transformer = OneHotEncoder()
>>> table = Table.from_dict({"col1": [1, 2, 1], "col2": [1, 2, 4]})
>>> transformer = transformer.fit(table, None)
>>> table.transform_table(transformer)
col1_1 col1_2 col2_1 col2_2 col2_4
0 1.0 0.0 1.0 0.0 0.0
1 0.0 1.0 0.0 1.0 0.0
2 1.0 0.0 0.0 0.0 1.0
"""
Marsmaennchen221 marked this conversation as resolved.
Show resolved Hide resolved
return transformer.transform(self)

def inverse_transform_table(self, transformer: InvertibleTableTransformer) -> Table:
"""
Invert the transformation applied by the given transformer.
Expand All @@ -1005,7 +1039,7 @@ def inverse_transform_table(self, transformer: InvertibleTableTransformer) -> Ta
Returns
-------
table : Table
The original table
The original table.

Raises
------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from safeds.data.tabular.transformation import OneHotEncoder


class TestInverseTransformTableOnOneHotEncoder:
class TestInverseTransformTable:
@pytest.mark.parametrize(
("table_to_fit", "column_names", "table_to_transform"),
[
Expand Down
120 changes: 120 additions & 0 deletions tests/safeds/data/tabular/containers/_table/test_transform_table.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import pytest
from safeds.data.tabular.containers import Table
from safeds.data.tabular.exceptions import TransformerNotFittedError, UnknownColumnNameError
from safeds.data.tabular.transformation import OneHotEncoder


class TestTransform:
Marsmaennchen221 marked this conversation as resolved.
Show resolved Hide resolved
@pytest.mark.parametrize(
("table", "column_names", "expected"),
[
(
Table.from_dict(
{
"col1": ["a", "b", "b", "c"],
},
),
None,
Table.from_dict(
{
"col1_a": [1.0, 0.0, 0.0, 0.0],
"col1_b": [0.0, 1.0, 1.0, 0.0],
"col1_c": [0.0, 0.0, 0.0, 1.0],
},
),
),
(
Table.from_dict(
{
"col1": ["a", "b", "b", "c"],
"col2": ["a", "b", "b", "c"],
},
),
["col1"],
Table.from_dict(
{
"col1_a": [1.0, 0.0, 0.0, 0.0],
"col1_b": [0.0, 1.0, 1.0, 0.0],
"col1_c": [0.0, 0.0, 0.0, 1.0],
"col2": ["a", "b", "b", "c"],
},
),
),
(
Table.from_dict(
{
"col1": ["a", "b", "b", "c"],
"col2": ["a", "b", "b", "c"],
},
),
["col1", "col2"],
Table.from_dict(
{
"col1_a": [1.0, 0.0, 0.0, 0.0],
"col1_b": [0.0, 1.0, 1.0, 0.0],
"col1_c": [0.0, 0.0, 0.0, 1.0],
"col2_a": [1.0, 0.0, 0.0, 0.0],
"col2_b": [0.0, 1.0, 1.0, 0.0],
"col2_c": [0.0, 0.0, 0.0, 1.0],
},
),
),
],
ids=["all columns", "one column", "multiple columns"],
)
def test_should_return_transformed_table(
self,
table: Table,
column_names: list[str] | None,
expected: Table,
) -> None:
transformer = OneHotEncoder().fit(table, column_names)
assert table.transform_table(transformer) == expected

def test_should_not_change_original_table(self) -> None:
table = Table.from_dict(
{
"col1": ["a", "b", "c"],
},
)

transformer = OneHotEncoder().fit(table, None)
table.transform_table(transformer)

expected = Table.from_dict(
{
"col1": ["a", "b", "c"],
},
)

assert table == expected

def test_should_raise_if_column_not_found(self) -> None:
table_to_fit = Table.from_dict(
{
"col1": ["a", "b", "c"],
},
)

transformer = OneHotEncoder().fit(table_to_fit, None)

table_to_transform = Table.from_dict(
{
"col2": ["a", "b", "c"],
},
)

with pytest.raises(UnknownColumnNameError):
table_to_transform.transform_table(transformer)

def test_should_raise_if_not_fitted(self) -> None:
table = Table.from_dict(
{
"col1": ["a", "b", "c"],
},
)

transformer = OneHotEncoder()

with pytest.raises(TransformerNotFittedError):
table.transform_table(transformer)