Skip to content

DatetimeEncoder.get_feature_names_out fails because of the wrong inheritance #1621

Description

@glemaitre

Here is a reproducer:

import pandas as pd
from sklearn.utils.validation import check_is_fitted
from skrub import DatetimeEncoder

login = pd.to_datetime(
    pd.Series(
        ["2024-05-13T12:05:36", None, "2024-05-15T13:46:02"], name="login")
)
encoder = DatetimeEncoder()
encoder.fit_transform(login)
check_is_fitted(encoder)  # pass
encoder.get_feature_names_out()  # error

It fails with:

---------------------------------------------------------------------------
NotFittedError                            Traceback (most recent call last)
Cell In[3], line 12
     10 encoder.fit_transform(login)
     11 check_is_fitted(encoder)  # pass
---> 12 encoder.get_feature_names_out()  # error

File [~/Documents/packages/python-stack/skrub/skrub/skrub/_apply_to_cols.py:143](http://localhost:8889/lab/tree/~/Documents/packages/python-stack/skrub/skrub/skrub/_apply_to_cols.py#line=142), in SingleColumnTransformer.get_feature_names_out(self, input_features)
    126 def get_feature_names_out(self, input_features=None):
    127     """Return a list of features generated by the transformer.
    128 
    129     Each feature has format ``{input_name}_{n_component}`` where ``input_name``
   (...)    141         The list of feature names.
    142     """
--> 143     check_is_fitted(self, "n_components_")
    144     num_digits = len(str(self.n_components_ - 1))
    145     return [
    146         f"{self.input_name_}_{str(i).zfill(num_digits)}"
    147         for i in range(self.n_components_)
    148     ]

File [~/Documents/packages/python-stack/scikit-learn/scikit-learn/sklearn/utils/validation.py:1774](http://localhost:8889/lab/tree/~/Documents/packages/python-stack/scikit-learn/scikit-learn/sklearn/utils/validation.py#line=1773), in check_is_fitted(estimator, attributes, msg, all_or_any)
   1771     return
   1773 if not _is_fitted(estimator, attributes, all_or_any):
-> 1774     raise NotFittedError(msg % {"name": type(estimator).__name__})

NotFittedError: This DatetimeEncoder instance is not fitted yet. Call 'fit' with appropriate arguments before using this estimator.

As shown, the encoder is actually fitted. But our implementation of get_feature_names_out will request for a n_components_ which does not exist for DatetimeEncoder.

Since get_feature_names_out is implemented in SingleColumnTransformer, I think that we should have an agnostic get_feature_names_out that does not check for a specific attribute and specialize for the n_component_ for the encoder/transformer that have this attribute.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions