Skip to content

Commit 16f4ac9

Browse files
thomasjpfanadrinjalali
authored andcommitted
DEP Deprecate None in FeatureUnion (scikit-learn#15053)
* ENH Deprecates None in feature union * ENH Deprecates None in feature union * DOC Adds todo * DOC Adds TODO * STY * CLN Address @adrinjalali comments * DOC Adds whats_new * TST Better checks * CLN Nicer asserts * CLN Address nicholas comments * STY Fix flake8
1 parent 24a50e5 commit 16f4ac9

File tree

3 files changed

+55
-18
lines changed

3 files changed

+55
-18
lines changed

doc/whats_new/v0.22.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,10 @@ Changelog
528528
the final estimator does.
529529
:pr:`13806` by :user:`Anaël Beaugnon <ab-anssi>`.
530530

531+
- |API| `None` as a transformer is now deprecated in
532+
:class:`pipeline.FeatureUnion`. Please use `'drop'` instead. :pr:`15053` by
533+
`Thomas Fan`_.
534+
531535
- |Fix| The `fit` in :class:`~pipeline.FeatureUnion` now accepts `fit_params`
532536
to pass to the underlying transformers. :pr:`15119` by `Adrin Jalali`_.
533537

sklearn/pipeline.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
from collections import defaultdict
1313
from itertools import islice
14+
import warnings
1415

1516
import numpy as np
1617
from scipy import sparse
@@ -754,7 +755,7 @@ class FeatureUnion(TransformerMixin, _BaseComposition):
754755
Parameters of the transformers may be set using its name and the parameter
755756
name separated by a '__'. A transformer may be replaced entirely by
756757
setting the parameter with its name to another transformer,
757-
or removed by setting to 'drop' or ``None``.
758+
or removed by setting to 'drop'.
758759
759760
Read more in the :ref:`User Guide <feature_union>`.
760761
@@ -764,6 +765,9 @@ class FeatureUnion(TransformerMixin, _BaseComposition):
764765
List of transformer objects to be applied to the data. The first
765766
half of each tuple is the name of the transformer.
766767
768+
.. versionchanged:: 0.22
769+
Deprecated `None` as a transformer in favor of 'drop'.
770+
767771
n_jobs : int or None, optional (default=None)
768772
Number of jobs to run in parallel.
769773
``None`` means 1 unless in a :obj:`joblib.parallel_backend` context.
@@ -840,7 +844,14 @@ def _validate_transformers(self):
840844

841845
# validate estimators
842846
for t in transformers:
843-
if t is None or t == 'drop':
847+
# TODO: Remove in 0.24 when None is removed
848+
if t is None:
849+
warnings.warn("Using None as a transformer is deprecated "
850+
"in version 0.22 and will be removed in "
851+
"version 0.24. Please use 'drop' instead.",
852+
DeprecationWarning)
853+
continue
854+
if t == 'drop':
844855
continue
845856
if (not (hasattr(t, "fit") or hasattr(t, "fit_transform")) or not
846857
hasattr(t, "transform")):

sklearn/tests/test_pipeline.py

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,7 @@ def test_set_feature_union_steps():
898898
assert ['mock__x5'] == ft.get_feature_names()
899899

900900

901+
# TODO: Remove parametrization in 0.24 when None is removed for FeatureUnion
901902
@pytest.mark.parametrize('drop', ['drop', None])
902903
def test_set_feature_union_step_drop(drop):
903904
mult2 = Mult(2)
@@ -911,25 +912,33 @@ def test_set_feature_union_step_drop(drop):
911912
assert_array_equal([[2, 3]], ft.fit_transform(X))
912913
assert ['m2__x2', 'm3__x3'] == ft.get_feature_names()
913914

914-
ft.set_params(m2=drop)
915-
assert_array_equal([[3]], ft.fit(X).transform(X))
916-
assert_array_equal([[3]], ft.fit_transform(X))
915+
with pytest.warns(None) as record:
916+
ft.set_params(m2=drop)
917+
assert_array_equal([[3]], ft.fit(X).transform(X))
918+
assert_array_equal([[3]], ft.fit_transform(X))
917919
assert ['m3__x3'] == ft.get_feature_names()
920+
assert record if drop is None else not record
918921

919-
ft.set_params(m3=drop)
920-
assert_array_equal([[]], ft.fit(X).transform(X))
921-
assert_array_equal([[]], ft.fit_transform(X))
922+
with pytest.warns(None) as record:
923+
ft.set_params(m3=drop)
924+
assert_array_equal([[]], ft.fit(X).transform(X))
925+
assert_array_equal([[]], ft.fit_transform(X))
922926
assert [] == ft.get_feature_names()
923-
924-
# check we can change back
925-
ft.set_params(m3=mult3)
926-
assert_array_equal([[3]], ft.fit(X).transform(X))
927-
928-
# Check 'drop' step at construction time
929-
ft = FeatureUnion([('m2', drop), ('m3', mult3)])
930-
assert_array_equal([[3]], ft.fit(X).transform(X))
931-
assert_array_equal([[3]], ft.fit_transform(X))
927+
assert record if drop is None else not record
928+
929+
with pytest.warns(None) as record:
930+
# check we can change back
931+
ft.set_params(m3=mult3)
932+
assert_array_equal([[3]], ft.fit(X).transform(X))
933+
assert record if drop is None else not record
934+
935+
with pytest.warns(None) as record:
936+
# Check 'drop' step at construction time
937+
ft = FeatureUnion([('m2', drop), ('m3', mult3)])
938+
assert_array_equal([[3]], ft.fit(X).transform(X))
939+
assert_array_equal([[3]], ft.fit_transform(X))
932940
assert ['m3__x3'] == ft.get_feature_names()
941+
assert record if drop is None else not record
933942

934943

935944
def test_step_name_validation():
@@ -1127,7 +1136,7 @@ def test_pipeline_param_error():
11271136
(FeatureUnion([('mult1', Mult()), ('mult2', Mult())]),
11281137
r'\[FeatureUnion\].*\(step 1 of 2\) Processing mult1.* total=.*\n'
11291138
r'\[FeatureUnion\].*\(step 2 of 2\) Processing mult2.* total=.*\n$'),
1130-
(FeatureUnion([('mult1', None), ('mult2', Mult()), ('mult3', None)]),
1139+
(FeatureUnion([('mult1', 'drop'), ('mult2', Mult()), ('mult3', 'drop')]),
11311140
r'\[FeatureUnion\].*\(step 1 of 1\) Processing mult2.* total=.*\n$')
11321141
], ['fit', 'fit_transform', 'fit_predict'])
11331142
if hasattr(est, method) and not (
@@ -1173,3 +1182,16 @@ def transform(self, X, y=None):
11731182

11741183
t.fit(X, y, a=0)
11751184
t.fit_transform(X, y, a=0)
1185+
1186+
1187+
# TODO: Remove in 0.24 when None is removed
1188+
def test_feature_union_warns_with_none():
1189+
msg = (r"Using None as a transformer is deprecated in version 0\.22 and "
1190+
r"will be removed in version 0\.24\. Please use 'drop' instead\.")
1191+
with pytest.warns(DeprecationWarning, match=msg):
1192+
union = FeatureUnion([('multi1', None), ('multi2', Mult())])
1193+
1194+
X = [[1, 2, 3], [4, 5, 6]]
1195+
1196+
with pytest.warns(DeprecationWarning, match=msg):
1197+
union.fit_transform(X)

0 commit comments

Comments
 (0)