Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions DashAI/back/converters/category/feature_engineering.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from typing import Final

from DashAI.back.converters.base_converter import BaseConverter
from DashAI.back.core.utils import MultilingualString
from DashAI.back.static.icons import Icon


class FeatureEngineeringConverter(BaseConverter):
"""Base class for converters that derive new features from existing columns.

Feature engineering converters compute new columns out of one or more
existing columns instead of modifying them in place. Examples include
ColumnArithmetic (arithmetic combinations of two numeric columns),
NumericExpansion (log1p, square, and square-root expansions of a numeric
column), and ColumnConcat (string concatenation of two text/categorical
columns).

Use these converters to craft new signals for models when the raw
columns alone are not expressive enough.
"""

CATEGORY = MultilingualString(
en="Feature Engineering",
es="Ingeniería de Características",
pt="Engenharia de Características",
de="Feature-Engineering",
zh="特征工程",
)
ICON: Final[str] = Icon.Functions.value
COLOR: Final[str] = "rgb(0, 188, 212)"
76 changes: 70 additions & 6 deletions DashAI/back/converters/scikit_learn/simple_imputer.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import TYPE_CHECKING, Union

from sklearn.impute import SimpleImputer as SimpleImputerOperation

from DashAI.back.converters.category.basic_preprocessing import (
Expand All @@ -20,6 +22,9 @@
from DashAI.back.types.dashai_data_type import DashAIDataType
from DashAI.back.types.value_types import Float, Integer

if TYPE_CHECKING:
from DashAI.back.dataloaders.classes.dashai_dataset import DashAIDataset


class SimpleImputerSchema(BaseSchema):
"""Schema for configuring the SimpleImputer converter.
Expand Down Expand Up @@ -103,9 +108,15 @@ class SimpleImputer(

Columns with all-missing values are handled according to the
``keep_empty_features`` flag. When ``add_indicator=True``, a
``MissingIndicator`` binary matrix is stacked onto the output. All
output columns are typed as ``Float64`` in DashAI regardless of the
original column type.
``MissingIndicator`` binary matrix is stacked onto the output.

Output typing preserves the original column type whenever the strategy
does not force a fractional result: ``"most_frequent"`` and
``"constant"`` never perform arithmetic, so the source type (Integer,
Float, or Categorical) is kept. For ``"mean"``/``"median"`` the computed
per-column statistic is inspected, and an originally-Integer column
stays ``Integer`` if that statistic happens to be a whole number (e.g. a
median over an odd count of integers); otherwise it becomes ``Float64``.

Wraps ``sklearn.impute.SimpleImputer``.

Expand Down Expand Up @@ -170,20 +181,73 @@ def __init__(self, **kwargs):
"""
super().__init__(**kwargs)

def fit(
self, x: "DashAIDataset", y: Union["DashAIDataset", None] = None
) -> "SimpleImputer":
"""Fit the imputer, remembering input types and column order.

These are needed by ``get_output_type`` to preserve the original
column type instead of always coercing to ``Float64``.

Parameters
----------
x : DashAIDataset
The input dataset to fit the imputer on.
y : DashAIDataset, optional
Ignored; present for API consistency.

Returns
-------
SimpleImputer
The fitted imputer instance (self).
"""
if hasattr(x, "types") and x.types is not None:
self._input_types = dict(x.types)
self._input_columns = {name: idx for idx, name in enumerate(x.column_names)}
return super().fit(x, y)

def get_output_type(self, column_name: str = None) -> DashAIDataType:
"""Return the DashAI data type produced by this converter for a column.

Parameters
----------
column_name : str, optional
Not used; all output columns share the
same type. Defaults to None.
The name of the output column. Defaults to None.

Returns
-------
DashAIDataType
A Float type backed by ``pyarrow.float64()``.
``Integer`` for the binary ``MissingIndicator`` columns appended
when ``add_indicator=True``. Otherwise, the original column type
for ``"most_frequent"``/``"constant"`` (no arithmetic is performed
on the values), or for ``"mean"``/``"median"``, ``Integer`` if the
source column was an Integer and the computed statistic is a
whole number — otherwise a Float type backed by
``pyarrow.float64()``.
"""
import pyarrow as pa

if column_name and str(column_name).startswith("missingindicator_"):
return Integer(arrow_type=pa.int64())

input_types = getattr(self, "_input_types", None)
input_type = input_types.get(column_name) if input_types else None

if self.strategy in ("most_frequent", "constant"):
if input_type is not None:
return input_type
return Float(arrow_type=pa.float64())

if isinstance(input_type, Integer):
columns = getattr(self, "_input_columns", None)
statistics = getattr(self, "statistics_", None)
if (
columns is not None
and statistics is not None
and column_name in columns
):
value = statistics[columns[column_name]]
if float(value).is_integer():
return Integer(arrow_type=pa.int64())

return Float(arrow_type=pa.float64())
Loading
Loading