[MNT] rename Winsoriser public name to british spelling - #967
Conversation
solegalli
left a comment
There was a problem hiding this comment.
Hey @favourone
Great job here indeed. I'd like the old version of the class to raise a future warning directing the user to use the new version instead. Could you check how that could work?
| :class:`Winsoriser()` caps maximum and/or minimum values of a variable at automatically | ||
| determined values. | ||
|
|
||
| ``Winsorizer`` remains available as a backward-compatible alias. |
There was a problem hiding this comment.
Could we remove this from the user guide?
|
|
||
| - :doc:`api_doc/outliers/ArbitraryOutlierCapper`: caps maximum and minimum values at user defined values | ||
| - :doc:`api_doc/outliers/Winsorizer`: caps maximum or minimum values using statistical parameters | ||
| - :doc:`Winsoriser <api_doc/outliers/Winsorizer>`: caps maximum or minimum values using statistical parameters |
There was a problem hiding this comment.
| - :doc:`Winsoriser <api_doc/outliers/Winsorizer>`: caps maximum or minimum values using statistical parameters | |
| - :doc:`<api_doc/outliers/Winsorizer>`: caps maximum or minimum values using statistical parameters |
| return feature_names | ||
|
|
||
|
|
||
| # Backward-compatible alias for the original American spelling. |
There was a problem hiding this comment.
Hey @favourone
Could we explore the option of adding a future warning that is raised as soon as the user initialises the old version of the class saying Winsorizer was deprecated in favour of Winsoriser in version 2.0.0 and will be removed in version 2.1.0. To silence this warning use Winsoriser instead.
| from feature_engine.outliers import Winsoriser, Winsorizer | ||
|
|
||
|
|
||
| def test_winsorizer_is_backward_compatible_alias(): |
There was a problem hiding this comment.
Hey @favourone is this the best way to ensure both classes are identical? Or should we use parametrize to test both classes in all tests?
Could we also add a test for the warning in the old version of the class?
solegalli
left a comment
There was a problem hiding this comment.
Hi @favourone
This is good to merge. Great work.
Similarly to the other PR, could you please rename rename the files in the user guide and api folder to MeanNormalisationScalerWinsoriser.rst and then update the toctrees that reference them to propagate the spelling to the docs URL?
Thanks a lot!
| feature_names = feature_names + self._get_new_features_name() | ||
| return feature_names | ||
|
|
||
|
|
There was a problem hiding this comment.
| # TODO: remove in version 2.1.0 |
Removed the module-level `import pandas as pd` and `import numpy as np`; X type hints now use narwhals' IntoDataFrame. WinsorizerBase.fit/transform (shared base) were already migrated on origin/narwhals-outliers-base; this change covers the Winsoriser-specific piece: transform()'s add_indicators path, which compares the capped output against the original input to build per-tail boolean flag columns and previously only worked on pandas. Benchmarked the add_indicators comparison+concat step at 10k/50k/100k rows x 1/2/10 columns: pandas-native (boolean comparison + pd.concat) is up to ~3x faster than the narwhals with_columns equivalent on pandas input, and the loss grows with column count (1 col: narwhals-on-pandas was actually faster; 10 cols: ~2-3x slower). That crosses the "keep pandas fast path" threshold, so transform() splits on `nwd.is_pandas_dataframe`, matching MissingIndicator's precedent for its own indicator-building step: pandas keeps its existing comparison+concat logic (now obtaining the `pd` module via `nw.from_native(...).__native_namespace__()` instead of importing it), and a new narwhals with_columns path (per-column Series comparison, cast to Float64) covers polars and other backends. Preserved the Winsoriser/Winsorizer deprecation exactly as-is: Winsoriser is the current public name (renamed to the British spelling in #967); Winsorizer is a deprecated subclass that raises the same FutureWarning on __init__ and will be removed in 2.1.0. Note this is the reverse of what one might guess from the class names alone. Tests: converted tests/test_outliers/test_winsorizer.py from pandas-only fixtures (df_normal_dist, df_vartypes, df_na) to local dicts parametrized over `make_df` in [pd.DataFrame, pl.DataFrame], asserting identical capping values, indicator columns, and get_feature_names_out() on both backends for the same input. Missing-value dicts use None instead of np.nan in string columns, since polars' DataFrame constructor rejects a float NaN mixed into a string column. A helper filters both pandas' NaN and polars' None representations of a missing value when comparing outputs cross-backend. Docs: verified every doc example in docs/user_guide/outliers/Winsoriser.rst against actual output (network access to fetch_openml's house_prices dataset was available; outputs matched exactly, no changes needed) and added a "With polars" section covering add_indicators, matching the pattern used in other migrated user guides. Added a verified "With polars" example to the class docstring. Verified: tests/test_outliers/test_winsorizer.py 93 passed. Full tests/test_outliers suite: 123 passed / 3 pre-existing failures in test_check_estimator_outliers.py (confirmed identical against a baseline run of origin/narwhals-outliers-base: 83 passed / same 3 failures - sklearn's check_estimator feeds raw numpy arrays, which check_X() has always rejected per the narwhals migration's dataframe-only contract; predates this change). flake8 and mypy clean. sphinx -W build clean (only the pre-existing unrelated linkcode_resolve warning, confirmed present on the base branch too). Confirmed winsorizer.py and base_outlier.py import successfully and a full polars fit_transform (including add_indicators) runs correctly with pandas' own import blocked at the builtins level. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Summary
Winsoriseras the preferred public class name.Winsorizeras a backward-compatible alias.feature_engine.outliers.Tests
python -m pytest tests/test_outliers/test_winsorizer.py -q— 27 passedpython -m pytest tests/test_outliers -q— 60 passedflake8— passedgit diff --check— passedPart of #958.