From 34188153f4f4e4c38b9c731e31073ad6e42d5ba1 Mon Sep 17 00:00:00 2001 From: favour <2717216325@qq.com> Date: Wed, 22 Jul 2026 15:55:09 +0800 Subject: [PATCH 1/4] [ENH] add MeanNormalisationScaler public name --- README.md | 2 +- .../scaling/MeanNormalizationScaler.rst | 4 ++-- docs/index.rst | 2 +- .../scaling/MeanNormalizationScaler.rst | 20 ++++++++-------- feature_engine/scaling/__init__.py | 3 ++- feature_engine/scaling/mean_normalization.py | 14 +++++++---- tests/test_scaling/test_mean_normalization.py | 23 +++++++++++-------- 7 files changed, 41 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 76a9056bc..d6eeda624 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,7 @@ Please share your story by answering 1 quick question * ArcSinhTransformer ### Variable Scaling methods -* MeanNormalizationScaler +* MeanNormalisationScaler ### Variable Creation: * MathFeatures diff --git a/docs/api_doc/scaling/MeanNormalizationScaler.rst b/docs/api_doc/scaling/MeanNormalizationScaler.rst index a7ed38bd8..2cc963470 100644 --- a/docs/api_doc/scaling/MeanNormalizationScaler.rst +++ b/docs/api_doc/scaling/MeanNormalizationScaler.rst @@ -1,6 +1,6 @@ -MeanNormalizationScaler +MeanNormalisationScaler ======================= -.. autoclass:: feature_engine.scaling.MeanNormalizationScaler +.. autoclass:: feature_engine.scaling.MeanNormalisationScaler :members: diff --git a/docs/index.rst b/docs/index.rst index 6a05f7e9e..1148d9597 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -328,7 +328,7 @@ procedures to a subset of the variables only, check out the :doc:`api_doc/wrappe Feature-engine extends scikit-learn's scaling functionality with the following transformer: -- :doc:`api_doc/scaling/MeanNormalizationScaler`: scale variables using mean normalisation +- :doc:`MeanNormalisationScaler `: scale variables using mean normalisation Scikit-learn Wrapper: diff --git a/docs/user_guide/scaling/MeanNormalizationScaler.rst b/docs/user_guide/scaling/MeanNormalizationScaler.rst index 4cab88937..6e48f45eb 100644 --- a/docs/user_guide/scaling/MeanNormalizationScaler.rst +++ b/docs/user_guide/scaling/MeanNormalizationScaler.rst @@ -2,12 +2,12 @@ .. currentmodule:: feature_engine.scaling -MeanNormalizationScaler +MeanNormalisationScaler ======================= .. attention:: - **New in version 2.0:** When `variables` is `None`, :class:`MeanNormalizationScaler()` used to + **New in version 2.0:** When `variables` is `None`, :class:`MeanNormalisationScaler()` used to raise an error if the dataframe contained no numerical variables. You can now set the new parameter `return_empty` to `True` to make the transformer return an empty list of variables and skip the scaling instead, leaving the dataframe @@ -28,23 +28,25 @@ Mean normalisation is given by the following formula: X' = (X - Mean(X)) / (Max(X) - Min(X)) -:class:`MeanNormalizationScaler()` scales variables using mean normalisation. +:class:`MeanNormalisationScaler()` scales variables using mean normalisation. .. note:: - :class:`MeanNormalizationScaler()` only works with non-constant numerical variables. + :class:`MeanNormalisationScaler()` only works with non-constant numerical variables. If the variable is constant, the scaler will raise an error. + ``MeanNormalizationScaler`` remains available as a backward-compatible alias. + Python implementation --------------------- -We'll show how to use :class:`MeanNormalizationScaler()` through a toy dataset. Let's create +We'll show how to use :class:`MeanNormalisationScaler()` through a toy dataset. Let's create a toy dataset: .. code:: python import pandas as pd - from feature_engine.scaling import MeanNormalizationScaler + from feature_engine.scaling import MeanNormalisationScaler df = pd.DataFrame.from_dict( { @@ -81,12 +83,12 @@ First, let's make a list with the variable names: 'Height', ] -Now, let's set up :class:`MeanNormalizationScaler()`: +Now, let's set up :class:`MeanNormalisationScaler()`: .. code:: python # set up the scaler - scaler = MeanNormalizationScaler(variables = vars) + scaler = MeanNormalisationScaler(variables = vars) # fit the scaler scaler.fit(df) @@ -155,4 +157,4 @@ For tutorials about this and other feature engineering methods check out these r Both our book and courses are suitable for beginners and more advanced data scientists alike. By purchasing them you are supporting `Sole `_, -the main developer of feature-engine. \ No newline at end of file +the main developer of feature-engine. diff --git a/feature_engine/scaling/__init__.py b/feature_engine/scaling/__init__.py index 00137a550..eddb3fc47 100644 --- a/feature_engine/scaling/__init__.py +++ b/feature_engine/scaling/__init__.py @@ -3,8 +3,9 @@ scaling methods. """ -from .mean_normalization import MeanNormalizationScaler +from .mean_normalization import MeanNormalisationScaler, MeanNormalizationScaler __all__ = [ + "MeanNormalisationScaler", "MeanNormalizationScaler", ] diff --git a/feature_engine/scaling/mean_normalization.py b/feature_engine/scaling/mean_normalization.py index 320358838..c0ba2d6a6 100644 --- a/feature_engine/scaling/mean_normalization.py +++ b/feature_engine/scaling/mean_normalization.py @@ -37,9 +37,9 @@ fit_transform=_fit_transform_docstring, inverse_transform=_inverse_transform_docstring, ) -class MeanNormalizationScaler(BaseNumericalTransformer): +class MeanNormalisationScaler(BaseNumericalTransformer): """ - MeanNormalizationScaler() applies mean normalisation, which consists of subtracting + MeanNormalisationScaler() applies mean normalisation, which consists of subtracting the mean of each feature and then dividing the result by the value range, that is, the difference between its maximum and minimum value. The method aims to center the variables at 0, and rescale the distribution between -1 and 1. @@ -51,6 +51,8 @@ class MeanNormalizationScaler(BaseNumericalTransformer): More details in the :ref:`User Guide `. + The ``MeanNormalizationScaler`` spelling remains available as a + backward-compatible alias. Parameters ---------- @@ -89,10 +91,10 @@ class MeanNormalizationScaler(BaseNumericalTransformer): >>> import numpy as np >>> import pandas as pd - >>> from feature_engine.scaling import MeanNormalizationScaler + >>> from feature_engine.scaling import MeanNormalisationScaler >>> np.random.seed(42) >>> X = pd.DataFrame(dict(x = np.random.lognormal(size = 100))) - >>> mns = MeanNormalizationScaler() + >>> mns = MeanNormalisationScaler() >>> mns.fit(X) >>> X = mns.transform(X) >>> X.head() @@ -189,3 +191,7 @@ def inverse_transform(self, X: pd.DataFrame) -> pd.DataFrame: X[self.variables_] = X[self.variables_] * self.range_ + self.mean_ return X + + +# Backward-compatible alias for the original American spelling. +MeanNormalizationScaler = MeanNormalisationScaler diff --git a/tests/test_scaling/test_mean_normalization.py b/tests/test_scaling/test_mean_normalization.py index 600b89275..eb00d7484 100644 --- a/tests/test_scaling/test_mean_normalization.py +++ b/tests/test_scaling/test_mean_normalization.py @@ -4,10 +4,15 @@ import pytest from sklearn.exceptions import NotFittedError -from feature_engine.scaling import MeanNormalizationScaler +from feature_engine.scaling import MeanNormalisationScaler, MeanNormalizationScaler from tests.estimator_checks.fit_functionality_checks import check_return_empty +def test_mean_normalization_scaler_is_backward_compatible_alias(): + assert MeanNormalizationScaler is MeanNormalisationScaler + assert MeanNormalizationScaler().__class__ is MeanNormalisationScaler + + def test_transforming_int_vars(): # input test case df = pd.DataFrame( @@ -26,7 +31,7 @@ def test_transforming_int_vars(): } ) - transformer = MeanNormalizationScaler(variables=None) + transformer = MeanNormalisationScaler(variables=None) X = transformer.fit_transform(df) pd.testing.assert_frame_equal(X, expected_df) @@ -39,7 +44,7 @@ def test_transforming_int_vars(): def test_mean_normalization_plus_automatically_find_variables(df_vartypes): # test case 1: automatically select variables - transformer = MeanNormalizationScaler(variables=None) + transformer = MeanNormalisationScaler(variables=None) X = transformer.fit_transform(df_vartypes) # expected output @@ -68,7 +73,7 @@ def test_mean_normalization_plus_automatically_find_variables(df_vartypes): def test_mean_normalization_plus_user_passes_var_list(df_vartypes): # test case 2: user passes variables - transformer = MeanNormalizationScaler(variables="Age") + transformer = MeanNormalisationScaler(variables="Age") X = transformer.fit_transform(df_vartypes) # expected output @@ -95,21 +100,21 @@ def test_mean_normalization_plus_user_passes_var_list(df_vartypes): def test_fit_raises_error_if_na_in_df(df_na): # test case 3: when dataset contains na, fit method - transformer = MeanNormalizationScaler() + transformer = MeanNormalisationScaler() with pytest.raises(ValueError): transformer.fit(df_na) def test_transform_raises_error_if_na_in_df(df_vartypes, df_na): # test case 4: when dataset contains na, transform method - transformer = MeanNormalizationScaler() + transformer = MeanNormalisationScaler() transformer.fit(df_vartypes) with pytest.raises(ValueError): transformer.transform(df_na[["Name", "City", "Age", "Marks", "dob"]]) def test_non_fitted_error(df_vartypes): - transformer = MeanNormalizationScaler() + transformer = MeanNormalisationScaler() with pytest.raises(NotFittedError): transformer.transform(df_vartypes) @@ -124,10 +129,10 @@ def test_constant_columns_error(): } ) - transformer = MeanNormalizationScaler() + transformer = MeanNormalisationScaler() with pytest.raises(ValueError, match=re.escape("Division by zero is not allowed")): transformer.fit(df) def test_check_return_empty(): - check_return_empty(MeanNormalizationScaler()) + check_return_empty(MeanNormalisationScaler()) From 66431fc6db6c42aaa6189dcef2db9c469a306934 Mon Sep 17 00:00:00 2001 From: favour <2717216325@qq.com> Date: Fri, 24 Jul 2026 10:00:58 +0800 Subject: [PATCH 2/4] [ENH] deprecate MeanNormalizationScaler spelling --- docs/index.rst | 2 +- .../scaling/MeanNormalizationScaler.rst | 2 - feature_engine/scaling/mean_normalization.py | 21 ++++-- tests/test_scaling/test_mean_normalization.py | 66 +++++++++++++------ 4 files changed, 64 insertions(+), 27 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 1148d9597..4997984c4 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -328,7 +328,7 @@ procedures to a subset of the variables only, check out the :doc:`api_doc/wrappe Feature-engine extends scikit-learn's scaling functionality with the following transformer: -- :doc:`MeanNormalisationScaler `: scale variables using mean normalisation +- :doc:``: scale variables using mean normalisation Scikit-learn Wrapper: diff --git a/docs/user_guide/scaling/MeanNormalizationScaler.rst b/docs/user_guide/scaling/MeanNormalizationScaler.rst index 6e48f45eb..30952f06c 100644 --- a/docs/user_guide/scaling/MeanNormalizationScaler.rst +++ b/docs/user_guide/scaling/MeanNormalizationScaler.rst @@ -35,8 +35,6 @@ Mean normalisation is given by the following formula: :class:`MeanNormalisationScaler()` only works with non-constant numerical variables. If the variable is constant, the scaler will raise an error. - ``MeanNormalizationScaler`` remains available as a backward-compatible alias. - Python implementation --------------------- diff --git a/feature_engine/scaling/mean_normalization.py b/feature_engine/scaling/mean_normalization.py index c0ba2d6a6..cc8409c12 100644 --- a/feature_engine/scaling/mean_normalization.py +++ b/feature_engine/scaling/mean_normalization.py @@ -1,6 +1,7 @@ # Authors: Vasco Schiavo # License: BSD 3 clause +import warnings from typing import List, Optional, Union import pandas as pd @@ -51,9 +52,6 @@ class MeanNormalisationScaler(BaseNumericalTransformer): More details in the :ref:`User Guide `. - The ``MeanNormalizationScaler`` spelling remains available as a - backward-compatible alias. - Parameters ---------- {variables} @@ -193,5 +191,18 @@ def inverse_transform(self, X: pd.DataFrame) -> pd.DataFrame: return X -# Backward-compatible alias for the original American spelling. -MeanNormalizationScaler = MeanNormalisationScaler +class MeanNormalizationScaler(MeanNormalisationScaler): + def __init__( + self, + variables: Union[None, int, str, List[Union[str, int]]] = None, + return_empty: bool = False, + ) -> None: + warnings.warn( + "MeanNormalizationScaler was deprecated in favour of " + "MeanNormalisationScaler in version 2.0.0 and will be removed in " + "version 2.1.0. To silence this warning, use MeanNormalisationScaler " + "instead.", + FutureWarning, + stacklevel=2, + ) + super().__init__(variables=variables, return_empty=return_empty) diff --git a/tests/test_scaling/test_mean_normalization.py b/tests/test_scaling/test_mean_normalization.py index eb00d7484..997b396db 100644 --- a/tests/test_scaling/test_mean_normalization.py +++ b/tests/test_scaling/test_mean_normalization.py @@ -7,13 +7,34 @@ from feature_engine.scaling import MeanNormalisationScaler, MeanNormalizationScaler from tests.estimator_checks.fit_functionality_checks import check_return_empty +DEPRECATION_WARNING = ( + "MeanNormalizationScaler was deprecated in favour of " + "MeanNormalisationScaler in version 2.0.0 and will be removed in version 2.1.0. " + "To silence this warning, use MeanNormalisationScaler instead." +) -def test_mean_normalization_scaler_is_backward_compatible_alias(): - assert MeanNormalizationScaler is MeanNormalisationScaler - assert MeanNormalizationScaler().__class__ is MeanNormalisationScaler +@pytest.fixture( + params=[MeanNormalisationScaler, MeanNormalizationScaler], + ids=["MeanNormalisationScaler", "MeanNormalizationScaler"], +) +def transformer_class(request): + return request.param -def test_transforming_int_vars(): + +def make_transformer(transformer_class, **kwargs): + if transformer_class is MeanNormalizationScaler: + with pytest.warns(FutureWarning, match=re.escape(DEPRECATION_WARNING)): + return transformer_class(**kwargs) + return transformer_class(**kwargs) + + +def test_mean_normalization_scaler_raises_future_warning(): + with pytest.warns(FutureWarning, match=re.escape(DEPRECATION_WARNING)): + MeanNormalizationScaler() + + +def test_transforming_int_vars(transformer_class): # input test case df = pd.DataFrame( { @@ -31,7 +52,7 @@ def test_transforming_int_vars(): } ) - transformer = MeanNormalisationScaler(variables=None) + transformer = make_transformer(transformer_class, variables=None) X = transformer.fit_transform(df) pd.testing.assert_frame_equal(X, expected_df) @@ -42,9 +63,11 @@ def test_transforming_int_vars(): pd.testing.assert_frame_equal(Xit, df) -def test_mean_normalization_plus_automatically_find_variables(df_vartypes): +def test_mean_normalization_plus_automatically_find_variables( + df_vartypes, transformer_class +): # test case 1: automatically select variables - transformer = MeanNormalisationScaler(variables=None) + transformer = make_transformer(transformer_class, variables=None) X = transformer.fit_transform(df_vartypes) # expected output @@ -71,9 +94,9 @@ def test_mean_normalization_plus_automatically_find_variables(df_vartypes): pd.testing.assert_frame_equal(Xit, df_vartypes, rtol=10e-3) -def test_mean_normalization_plus_user_passes_var_list(df_vartypes): +def test_mean_normalization_plus_user_passes_var_list(df_vartypes, transformer_class): # test case 2: user passes variables - transformer = MeanNormalisationScaler(variables="Age") + transformer = make_transformer(transformer_class, variables="Age") X = transformer.fit_transform(df_vartypes) # expected output @@ -98,28 +121,28 @@ def test_mean_normalization_plus_user_passes_var_list(df_vartypes): pd.testing.assert_frame_equal(Xit, df_vartypes, rtol=10e-3) -def test_fit_raises_error_if_na_in_df(df_na): +def test_fit_raises_error_if_na_in_df(df_na, transformer_class): # test case 3: when dataset contains na, fit method - transformer = MeanNormalisationScaler() + transformer = make_transformer(transformer_class) with pytest.raises(ValueError): transformer.fit(df_na) -def test_transform_raises_error_if_na_in_df(df_vartypes, df_na): +def test_transform_raises_error_if_na_in_df(df_vartypes, df_na, transformer_class): # test case 4: when dataset contains na, transform method - transformer = MeanNormalisationScaler() + transformer = make_transformer(transformer_class) transformer.fit(df_vartypes) with pytest.raises(ValueError): transformer.transform(df_na[["Name", "City", "Age", "Marks", "dob"]]) -def test_non_fitted_error(df_vartypes): - transformer = MeanNormalisationScaler() +def test_non_fitted_error(df_vartypes, transformer_class): + transformer = make_transformer(transformer_class) with pytest.raises(NotFittedError): transformer.transform(df_vartypes) -def test_constant_columns_error(): +def test_constant_columns_error(transformer_class): # input test case df = pd.DataFrame( { @@ -129,10 +152,15 @@ def test_constant_columns_error(): } ) - transformer = MeanNormalisationScaler() + transformer = make_transformer(transformer_class) with pytest.raises(ValueError, match=re.escape("Division by zero is not allowed")): transformer.fit(df) -def test_check_return_empty(): - check_return_empty(MeanNormalisationScaler()) +def test_check_return_empty(transformer_class): + transformer = make_transformer(transformer_class) + if transformer_class is MeanNormalizationScaler: + with pytest.warns(FutureWarning, match=re.escape(DEPRECATION_WARNING)): + check_return_empty(transformer) + else: + check_return_empty(transformer) From 9f7a74e0ff94726bd60c499a600ab726076282eb Mon Sep 17 00:00:00 2001 From: favour <2717216325@qq.com> Date: Fri, 24 Jul 2026 11:54:49 +0800 Subject: [PATCH 3/4] [DOC] fix MeanNormalisationScaler documentation link --- docs/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.rst b/docs/index.rst index 4997984c4..6a05f7e9e 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -328,7 +328,7 @@ procedures to a subset of the variables only, check out the :doc:`api_doc/wrappe Feature-engine extends scikit-learn's scaling functionality with the following transformer: -- :doc:``: scale variables using mean normalisation +- :doc:`api_doc/scaling/MeanNormalizationScaler`: scale variables using mean normalisation Scikit-learn Wrapper: From 00e8603aecfd46b181489febc879de917265e191 Mon Sep 17 00:00:00 2001 From: favour <2717216325@qq.com> Date: Fri, 24 Jul 2026 18:53:39 +0800 Subject: [PATCH 4/4] [DOC] rename MeanNormalisationScaler documentation files --- ...{MeanNormalizationScaler.rst => MeanNormalisationScaler.rst} | 0 docs/api_doc/scaling/index.rst | 2 +- docs/index.rst | 2 +- ...{MeanNormalizationScaler.rst => MeanNormalisationScaler.rst} | 0 docs/user_guide/scaling/index.rst | 2 +- feature_engine/scaling/mean_normalization.py | 1 + 6 files changed, 4 insertions(+), 3 deletions(-) rename docs/api_doc/scaling/{MeanNormalizationScaler.rst => MeanNormalisationScaler.rst} (100%) rename docs/user_guide/scaling/{MeanNormalizationScaler.rst => MeanNormalisationScaler.rst} (100%) diff --git a/docs/api_doc/scaling/MeanNormalizationScaler.rst b/docs/api_doc/scaling/MeanNormalisationScaler.rst similarity index 100% rename from docs/api_doc/scaling/MeanNormalizationScaler.rst rename to docs/api_doc/scaling/MeanNormalisationScaler.rst diff --git a/docs/api_doc/scaling/index.rst b/docs/api_doc/scaling/index.rst index 892925f38..d49af7f1c 100644 --- a/docs/api_doc/scaling/index.rst +++ b/docs/api_doc/scaling/index.rst @@ -9,4 +9,4 @@ given columns. .. toctree:: :maxdepth: 1 - MeanNormalizationScaler + MeanNormalisationScaler diff --git a/docs/index.rst b/docs/index.rst index 6a05f7e9e..8c35fe84a 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -328,7 +328,7 @@ procedures to a subset of the variables only, check out the :doc:`api_doc/wrappe Feature-engine extends scikit-learn's scaling functionality with the following transformer: -- :doc:`api_doc/scaling/MeanNormalizationScaler`: scale variables using mean normalisation +- :doc:`api_doc/scaling/MeanNormalisationScaler`: scale variables using mean normalisation Scikit-learn Wrapper: diff --git a/docs/user_guide/scaling/MeanNormalizationScaler.rst b/docs/user_guide/scaling/MeanNormalisationScaler.rst similarity index 100% rename from docs/user_guide/scaling/MeanNormalizationScaler.rst rename to docs/user_guide/scaling/MeanNormalisationScaler.rst diff --git a/docs/user_guide/scaling/index.rst b/docs/user_guide/scaling/index.rst index b0d8eb0ff..33209e0b9 100644 --- a/docs/user_guide/scaling/index.rst +++ b/docs/user_guide/scaling/index.rst @@ -59,4 +59,4 @@ Scalers .. toctree:: :maxdepth: 1 - MeanNormalizationScaler + MeanNormalisationScaler diff --git a/feature_engine/scaling/mean_normalization.py b/feature_engine/scaling/mean_normalization.py index cc8409c12..c13949c3e 100644 --- a/feature_engine/scaling/mean_normalization.py +++ b/feature_engine/scaling/mean_normalization.py @@ -191,6 +191,7 @@ def inverse_transform(self, X: pd.DataFrame) -> pd.DataFrame: return X +# TODO: remove in version 2.1.0 class MeanNormalizationScaler(MeanNormalisationScaler): def __init__( self,