feature selection
machine learning
data preprocessing
feature engineering
data analysis

show feature names after feature selection

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

After feature selection, the transformed matrix usually has fewer columns, but the model output no longer tells you which original features survived. In scikit-learn, the standard way to recover those names is to use the selector's support mask or, in newer APIs, get_feature_names_out.

The Core Pattern

Feature selectors keep track of which columns were retained. That means you can fit the selector once, then ask for either:

  • a Boolean mask with get_support()
  • selected names with get_feature_names_out()

If your input started as a pandas DataFrame, this becomes straightforward.

python
1import pandas as pd
2from sklearn.feature_selection import SelectKBest, f_classif
3
4X = pd.DataFrame({
5    "age": [21, 35, 42, 29, 50],
6    "income": [30, 60, 80, 45, 95],
7    "visits": [5, 9, 10, 6, 12],
8    "country_score": [2, 3, 5, 2, 6],
9})
10y = [0, 1, 1, 0, 1]
11
12selector = SelectKBest(score_func=f_classif, k=2)
13selector.fit(X, y)
14
15mask = selector.get_support()
16selected_columns = X.columns[mask]
17
18print(mask)
19print(selected_columns.tolist())

This works across many selectors because get_support() is part of the selector interface.

Using get_feature_names_out

Many modern scikit-learn selectors also expose get_feature_names_out, which is often cleaner:

python
selected_names = selector.get_feature_names_out(X.columns)
print(selected_names)

That saves you from manually applying the mask.

If the estimator was fitted on a DataFrame with string column names, many selectors also remember feature_names_in_, so this can work:

python
print(selector.get_feature_names_out())

Still, passing the original column list explicitly is often the least surprising option.

Pipelines and Preprocessing

The task gets more interesting when feature selection happens after one-hot encoding or other transformations. Then the relevant names are no longer the raw DataFrame columns. You first need the post-preprocessing feature names, and only then can the selector mask them.

Example with ColumnTransformer and a selector:

python
1import pandas as pd
2from sklearn.compose import ColumnTransformer
3from sklearn.feature_extraction import DictVectorizer
4from sklearn.feature_selection import SelectFromModel
5from sklearn.linear_model import LogisticRegression
6from sklearn.pipeline import Pipeline
7from sklearn.preprocessing import OneHotEncoder, StandardScaler
8
9X = pd.DataFrame({
10    "age": [21, 35, 42, 29, 50],
11    "income": [30, 60, 80, 45, 95],
12    "city": ["A", "B", "B", "A", "C"],
13})
14y = [0, 1, 1, 0, 1]
15
16preprocessor = ColumnTransformer([
17    ("num", StandardScaler(), ["age", "income"]),
18    ("cat", OneHotEncoder(handle_unknown="ignore"), ["city"]),
19])
20
21X_prepared = preprocessor.fit_transform(X)
22feature_names = preprocessor.get_feature_names_out()
23
24selector = SelectFromModel(LogisticRegression(max_iter=1000))
25selector.fit(X_prepared, y)
26
27selected_names = selector.get_feature_names_out(feature_names)
28print(selected_names)

This is the pattern to remember: ask the preprocessor for names first, then pass those names into the selector.

Why This Matters

Being able to print selected names is not just for curiosity. It helps with:

  • model interpretability
  • debugging leakage or redundant features
  • documenting what the pipeline actually learned
  • stable downstream reporting

Without names, feature selection just produces anonymous columns.

Common Pitfalls

The most common mistake is indexing the original DataFrame columns after one-hot encoding. Once preprocessing expands or reorders features, the original names no longer match the transformed matrix.

Another mistake is assuming every selector exposes importances directly. Some selectors only expose a support mask, which is enough to recover names but not always enough to rank them.

A third issue is mixing NumPy arrays and DataFrames too early. If you drop column names before fitting, name recovery becomes harder because you have to track them manually.

Summary

  • Use get_support() to build a mask over the original feature names.
  • Prefer get_feature_names_out() when the selector supports it.
  • In pipelines, get names from the preprocessor first, then apply the selector.
  • Keep DataFrame column names around as long as possible for easier debugging.
  • Feature-name recovery is especially important after one-hot encoding and other expanding transforms.

Course illustration
Course illustration

All Rights Reserved.