Skip to content

feat: Enable EstimatorTransformer.get_feature_names_out via ClassNamePrefixFeaturesOutMixin mixin - #812

Merged
koaning merged 3 commits into
koaning:mainfrom
DMZ22:estimatortransformer-feature-names
Aug 30, 2026
Merged

feat: Enable EstimatorTransformer.get_feature_names_out via ClassNamePrefixFeaturesOutMixin mixin#812
koaning merged 3 commits into
koaning:mainfrom
DMZ22:estimatortransformer-feature-names

Conversation

@DMZ22

@DMZ22 DMZ22 commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Description

EstimatorTransformer inherits TransformerMixin, which does not supply get_feature_names_out, so the method simply isn't there:

>>> EstimatorTransformer(LinearRegression()).get_feature_names_out(None)
AttributeError: 'EstimatorTransformer' object has no attribute 'get_feature_names_out'

The practical symptom is the pipeline case, which fails even after fitting:

>>> make_pipeline(StandardScaler(), EstimatorTransformer(LinearRegression())).fit(X, y).get_feature_names_out()
AttributeError: Estimator estimatortransformer does not provide get_feature_names_out.

The transformer's output is not one-to-one with the input columns — transform returns one column per target for a multi-output estimator and reshapes to a single column otherwise — so OneToOneFeatureMixin would be wrong here. The sklearn convention for this shape is ClassNamePrefixFeaturesOutMixin plus a _n_features_out, which is what this adds; n_outputs_ is recorded during fit.

single output   -> ['estimatortransformer0']
two targets     -> ['estimatortransformer0', 'estimatortransformer1']
in a pipeline   -> ['estimatortransformer0']
before fit      -> NotFittedError   (rather than AttributeError)

In every case the number of names equals transform(X).shape[1], which is asserted in the tests rather than assumed. A side benefit is that set_output(transform="pandas") now yields a properly-named DataFrame instead of failing.

@koaning — this is the change you green-lit on #533 back in 2022 ("Yes please!"); @CarloLepelaars offered then but no PR followed, and nothing open touches this file, so I hope it's helpful rather than stepping on anyone.

Fixes #533

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

Checklist:

  • My code follows the style guidelines (ruff) — ruff check and ruff format --check both clean
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation — the method is inherited API, so nothing in the docs asserts its absence; happy to add a line if you'd like one
  • I have added tests that prove my fix is effective or that my feature works
  • I have added tests to check whether the new feature adheres to the sklearn convention — the existing parametrize_with_checks suite still passes, and the names/width equality is asserted
  • New and existing unit tests pass locally with my changes

tests/test_meta/ goes from 1073 passed to 1110 passed with the same 15 pre-existing collection errors (missing pyarrow locally). Reverting only estimator_transformer.py while keeping the tests fails 37 of them, so they do guard the change.


One thing I found while measuring the output width, which I have not touched because it is a separate bug and a behaviour change:

transform does output.reshape(-1, 1) whenever multi_output_ is False. With predict_func="predict_proba" and a 1-D y, predict_proba returns (n_samples, n_classes), so the reshape multiplies the rows:

X has 60 rows, 3-class y
  estimator_.predict_proba(X) -> (60, 3)
  transform(X)                -> (180, 1)      # 60 samples in, 180 rows out

The class docstring records this too — its example is 150 samples with predict_func="predict_proba" and states Shape of transformed data: (300, 1). Happy to open a separate issue, or a PR, if you'd like it fixed.

EstimatorTransformer inherits TransformerMixin, which does not supply
get_feature_names_out, so calling it raised AttributeError and any
pipeline containing the transformer could not report its feature names
either.

Its output is not one-to-one with the input columns - one column per
target, or a single column otherwise - so it now also inherits
ClassNamePrefixFeaturesOutMixin and exposes _n_features_out, which is the
sklearn convention for that shape. n_outputs_ is recorded during fit.
@CarloLepelaars

Copy link
Copy Markdown
Contributor

Appreciate you picking this up. I forgot about it

@FBruzzesi FBruzzesi changed the title Give EstimatorTransformer get_feature_names_out feat: Enable EstimatorTransformer.get_feature_names_out via ClassNamePrefixFeaturesOutMixin mixin Jul 26, 2026
@FBruzzesi FBruzzesi added the enhancement New feature or request label Jul 26, 2026

@FBruzzesi FBruzzesi left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution @DMZ22 - I think the changes are totally fine.

The only issue I see is that ClassNamePrefixFeaturesOutMixin was introduced in scikit-learn 1.2, and we currently allow scikit-learn 1.0+ . @koaning what's your take in bumping the minimum scikit-learn version dependency?

@koaning

koaning commented Aug 30, 2026

Copy link
Copy Markdown
Owner

I've been behind on reviews, sorry about that.

I think I am cool with the version bump. It's been a few years at this point and the main thing that's important is that it doesn't increase the maintainance burden for us.

@koaning
koaning merged commit f0ac870 into koaning:main Aug 30, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] 'EstimatorTransformer' object has no attribute 'get_feature_names_out'

4 participants