Skip to content

Encoders that are f(X, y) can produce nan results when y has non-standard index and X becomes an np.ndarray #376

Description

@noahjgreen295

Describe the bug
In encoders where the feature encoding is a function of both the feature and the target (e.g. feature_engine.encoding.MeanEncoder), resulting encoding can become all nan if:

  • Feature DataFrame X is transformed upstream into an np.ndarray by a standard sklearn transformer.
    and
  • Feature DataFrame X has an index other than the standard contiguous 0-based default

The error occurs in the concatenation step within the encoder, and is caused by an index mismatch resulting from the preceding array transformation.

I have tested all the feature_engine.encoding transformers and only the following three have the issue:

This was first reported by @bmreiniger here, and unit tests for fix will be based on his sample code here.

To Reproduce
Derived from @bmreiniger code here. Using feature_engine.encoding.MeanEncoder as example:

    import numpy as np
    import pandas as pd
  
    from feature_engine.encoding import MeanEncoder
    
    from sklearn.impute import SimpleImputer

    # test dataframe; setup for a transfromation where
    # coded version of 'x' will be a function of target 'y'
    df: pd.DataFrame = pd.DataFrame({
        'x': ['a', 'a', 'b', 'b', 'c', 'c'],
        'y': [1, 0, 1, 0, 1, 0],
    })
    # Key - "non-standard" index that is not the usual
    # contiguous range starting a t 0
    df.index = [101, 105, 42, 76, 88, 92]

    # Set up for standard pipeline/training etc.
    X: pd.DataFrame = df[["x"]]
    y: pd.Series = df["y"]

    # Will serve as a no-op whose chief purpose is to turn the
    # X into an np.ndarray
    si = SimpleImputer(strategy="constant", fill_value="a")

    # Encoder encodes X as a function of y; this is what
    # breaks down when X becomes an array and indexes don't accidentally match in final
    # concantenation
    encoder = MeanEncoder()

    # Sequence leading to issue:
    # 1) X becomes an array
    assert type(X) == pd.DataFrame
    X_2: np.array = si.fit_transform(X)
    assert type(X_2) == np.ndarray

    # 2) Encoder encodes as function of X, y
    df_result: pd.DataFrame = encoder.fit_transform(X_2, y)
    assert type(df_result) == pd.DataFrame

    # Assertion fails: breakdown in index matches causes results to be all nan
    assert all(df_result.iloc[:, 0].notnull())

Expected behavior
In example above, output DataFrame df_result should have meaningful encoded values, not all nan.

Desktop (please complete the following information):

  • OS: Mac OS 11.6
  • Versions: feature-engine 1.2.0, Python 3.9.10, Pandas 1.3.4, numpy 1.22.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    maintenanceimprove code and maintenance

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions