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.
Here is a reproducer:
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
encoderis actually fitted. But our implementation ofget_feature_names_outwill request for an_components_which does not exist forDatetimeEncoder.Since
get_feature_names_outis implemented inSingleColumnTransformer, I think that we should have an agnosticget_feature_names_outthat does not check for a specific attribute and specialize for then_component_for the encoder/transformer that have this attribute.