Skip to content

Commit b3ab8f6

Browse files
authored
Exposing conversion to Float32 in the Cleaner (#1440)
1 parent 37216b3 commit b3ab8f6

3 files changed

Lines changed: 48 additions & 12 deletions

File tree

CHANGES.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ Changes
8383

8484
- The :class:`TableReport` now supports Series in addition to Dataframes. :pr:`1420` by :user:`Vitor Pohlenz<vitorpohlenz>`.
8585

86+
- The :class:`Cleaner` now exposes a parameter to convert numerical values to float32. :pr:`1440` by
87+
:user:`Riccardo Cappuzzo<rcap107>`.
88+
89+
8690
Bugfixes
8791
--------
8892
- Fixed a bug that caused the :class:`StringEncoder` and :class:`TextEncoder` to raise an exception if the

skrub/_table_vectorizer.py

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,10 @@ class Cleaner(TransformerMixin, BaseEstimator):
182182
datetime_format : str, default=None
183183
The format to use when parsing dates. If None, the format is inferred.
184184
185+
numeric_dtype : "float32" or None, default=None
186+
If set to ``float32``, convert numeric columns to ``np.float32`` dtype. If
187+
``None``, numerical dtypes are not modified.
188+
185189
n_jobs : int, default=None
186190
Number of jobs to run in parallel.
187191
``None`` means 1 unless in a joblib ``parallel_backend`` context.
@@ -225,11 +229,10 @@ class Cleaner(TransformerMixin, BaseEstimator):
225229
- ``ToStr()``: convert columns to strings, unless they are numerical,
226230
categorical, or datetime.
227231
228-
The ``Cleaner`` object should only be used for preliminary sanitizing of
229-
the data because it does not perform any transformations on numeric columns.
230-
On the other hand, the ``TableVectorizer`` converts numeric columns to ``float32``
231-
and ensures that null values are represented with NaNs, which can be handled
232-
correctly by downstream scikit-learn estimators.
232+
If ``numeric_dtype`` is set to ``float32``, the ``Cleaner`` will also convert
233+
numeric columns to ``np.float32`` dtype, ensuring a consistent representation
234+
of numbers and missing values. This can be useful if the ``Cleaner``
235+
is used as a preprocessing step in a skrub pipeline.
233236
234237
Examples
235238
--------
@@ -288,6 +291,11 @@ class Cleaner(TransformerMixin, BaseEstimator):
288291
TableVectorizer :
289292
Process columns of a dataframe and convert them to a numeric (vectorized)
290293
representation.
294+
295+
ToFloat32 :
296+
Convert numeric columns to ``np.float32``, to have consistent numeric
297+
types and representation of missing values. More informative columns (e.g.,
298+
categorical or datetime) are not converted.
291299
"""
292300

293301
def __init__(
@@ -296,12 +304,14 @@ def __init__(
296304
drop_if_constant=False,
297305
drop_if_unique=False,
298306
datetime_format=None,
307+
numeric_dtype=None,
299308
n_jobs=1,
300309
):
301310
self.drop_null_fraction = drop_null_fraction
302311
self.drop_if_constant = drop_if_constant
303312
self.drop_if_unique = drop_if_unique
304313
self.datetime_format = datetime_format
314+
self.numeric_dtype = numeric_dtype
305315
self.n_jobs = n_jobs
306316

307317
def fit_transform(self, X, y=None):
@@ -322,13 +332,21 @@ def fit_transform(self, X, y=None):
322332
dataframe
323333
The transformed input.
324334
"""
335+
336+
add_tofloat32 = self.numeric_dtype == "float32"
337+
if self.numeric_dtype not in (None, "float32"):
338+
raise ValueError(
339+
"`numeric_dtype` must be one of"
340+
f"[`None`, `'float32'`]. Found {self.numeric_dtype}."
341+
)
342+
325343
all_steps = _get_preprocessors(
326344
cols=s.all(),
327345
drop_null_fraction=self.drop_null_fraction,
328346
drop_if_constant=self.drop_if_constant,
329347
drop_if_unique=self.drop_if_unique,
330348
n_jobs=self.n_jobs,
331-
add_tofloat32=False,
349+
add_tofloat32=add_tofloat32,
332350
datetime_format=self.datetime_format,
333351
)
334352
self._pipeline = make_pipeline(*all_steps)
@@ -539,7 +557,7 @@ class TableVectorizer(TransformerMixin, BaseEstimator):
539557
540558
Cleaner :
541559
Preprocesses each column of a dataframe with consistency checks and
542-
sanitization, eg of null values or dates.
560+
sanitization, e.g., of null values or dates.
543561
544562
Examples
545563
--------

skrub/tests/test_table_vectorizer.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -389,21 +389,35 @@ def test_cleaner_dtypes(X, dict_expected_types):
389389
assert dict_expected_types[col] == X_trans[col].dtype
390390

391391

392-
def test_convert_float32():
392+
def test_convert_float32(df_module):
393393
"""
394394
Test that the TableVectorizer converts float64 to float32
395395
when using the default parameters.
396396
"""
397397
X = _get_clean_dataframe()
398398
vectorizer = TableVectorizer()
399399
out = vectorizer.fit_transform(X)
400-
assert out.dtypes["float"] == "float32"
401-
assert out.dtypes["int"] == "float32"
400+
assert sbd.dtype(out["float"]) == "float32"
401+
assert sbd.dtype(out["int"]) == "float32"
402402

403+
# default behavior: keep numeric type
403404
vectorizer = Cleaner()
404405
out = vectorizer.fit_transform(X)
405-
assert sbd.is_float(out["float"])
406-
assert sbd.is_integer(out["int"])
406+
assert sbd.dtype(out["float"]) == sbd.dtype(X["float"])
407+
assert sbd.dtype(out["int"]) == sbd.dtype(X["int"])
408+
assert sbd.dtype(out["float"]) == sbd.dtype(X["float"])
409+
assert sbd.dtype(out["int"]) == sbd.dtype(X["int"])
410+
411+
vectorizer = Cleaner(numeric_dtype="float32")
412+
out = vectorizer.fit_transform(X)
413+
assert out.dtypes["float"] == "float32"
414+
assert out.dtypes["int"] == "float32"
415+
416+
417+
def test_cleaner_invalid_numeric_dtype():
418+
X = _get_clean_dataframe()
419+
with pytest.raises(ValueError, match="numeric_dtype.*must be one of"):
420+
Cleaner(numeric_dtype="wrong").fit_transform(X)
407421

408422

409423
def test_auto_cast_missing_categories():

0 commit comments

Comments
 (0)