Concepts / Univariate Feature Selection with f_classif and f_regression

Univariate Feature Selection with f_classif and f_regression

Univariate feature selection scores each feature separately against the target using a statistical test such as f_classif or f_regression, then discards features whose p-values are too high.

  • Programming

Why Fewer Columns Can Help

Many real datasets come with far more input columns than a model can comfortably use. Some of those columns carry useful information about what you want to predict. Others are noise: values that vary randomly and have no real connection to the target. Feature selection is the family of techniques for deciding which columns to keep before a model is trained on them.

This article focuses on one simple approach available in scikit-learn. A univariate method scores each feature, SelectPercentile turns those scores into a keep-or-drop decision based on a fixed share of the columns, and you then check the result. Keep one question in mind as you read: if you were told to keep half of a set of columns, what would you use to decide which half is worth keeping?

Scoring Each Feature on Its Own

Definition

Univariate feature selection scores each feature separately against the target using a statistical test such as f_classif or f_regression, then discards features whose p-values are too high.

The word univariate means one variable at a time. Every column is tested against the target separately, without asking how it interacts with the other columns. The result of each test is a p-value. A high p-value means the feature is unlikely to be related to the target, so it becomes a candidate for removal. A low p-value means the feature looks related to the target and is more likely to be kept.

The method needs two decisions. First, you choose a statistical test. The default for classification is f_classif, and f_regression is the matching choice for regression. Second, you choose a rule for discarding features based on the p-values that test produces. Every discarding rule uses a threshold, and the methods differ in how they compute that threshold.

Feature aloneone column at a timeStatistical testf_classif or f_regressionp-valueagainst the targetp-value too high?threshold from the ruleDiscard featureremovedKeep featurepasses to the modelscoredproducescomparedyesno
What happens to one feature, in order, from its individual test to the keep or discard decision?

Read the diagram as a single feature's journey. The feature is never compared with its neighbours at this stage. Its own p-value alone decides whether it is a candidate for removal, and the threshold set by the discarding rule determines where the line falls.

What do you think happens?

A feature gets a p-value of 0.8 against the target. Is it kept or discarded?

  • Kept

  • Discarded

Reveal answer
Answer:

Discarded

A high p-value means the feature is unlikely to be related to the target, so it becomes a candidate for removal. Features whose p-values are too high are removed by the discarding rule.

Keeping a Fixed Percentage with SelectPercentile

The two simplest discarding rules differ only in how the size of the kept set is specified. SelectKBest selects a fixed number k of features, so you say how many columns survive no matter how many columns the dataset has. SelectPercentile selects a fixed percentage of features, so you say what share of the columns survives and the count adjusts automatically as the dataset grows or shrinks.

The usage pattern has three steps. First, you create the selector with a percentile. The percentile argument is a number from 0 to 100 that sets the share of features to keep; 50 means half of the features. Second, you fit the selector on training data so that it can score the features against the training targets. Third, you transform the training data, which keeps only the selected columns.

Notice that fit uses the training targets, so the selector learns which features to keep from training data only. The same fitted selector is then used to transform the test data, so the model sees exactly the same columns it was trained on. Fitting on the training split alone is what keeps the test set honest.

Feature 0Feature 3keptFeature 1Feature 7keptFeature 2Feature 3top-rankedFeature 4Feature 5Feature 6Feature 7top-rankedFeature 8Feature 9keptkept
If you keep 20 percent of ten features, how does the set shrink from the full list to the top-ranked subset?
Worked example

Working out how many features SelectPercentile keeps

A dataset has 10 input features. You create SelectPercentile with a percentile of 20 and keep the top-ranked share. How many features survive, and which ones?

  1. 1
    Count the inputs

    There are 10 features before selection.

  2. 2
    Apply the percentage

    20 percent of 10 features is 2 features. The count is set by the share, so it scales with the width of the dataset.

  3. 3
    Rank by score

    Each feature has already been scored alone against the training target. Sort the features from strongest to weakest score.

  4. 4
    Keep the top share

    Keep the 2 highest-scoring features and discard the other 8.

Result

Two features survive. In the diagram these are Feature 3 and Feature 7, which were the top-ranked features in this made-up scoring. If the same pipeline later received 40 features, the same 20 percent setting would keep 8 features without any change to the code.

Reading the Boolean Mask

Transforming the data tells you how many features survived, but not which ones. The get_support method answers the second question. It returns a Boolean mask: an array with one True or False value per original feature. True marks a feature that was kept, and False marks a feature that was removed.

The position of each entry in the mask corresponds to the position of that feature in the original input. The mask is therefore a direct map from original column positions to keep-or-drop decisions. Its length always equals the number of input columns, not the number that survived.

Position 0True, keptPosition 1False, droppedPosition 2True, keptPosition 3True, keptPosition 4False, droppedPosition 5False, dropped
Given a True and False mask over six columns, which original positions are kept?
Worked example

Reading a six-feature mask

The mask returned by get_support is True, False, True, True, False, False. Which original features were kept?

  1. 1
    Pair each entry with a position

    Entry 0 belongs to position 0, entry 1 to position 1, and so on up to position 5.

  2. 2
    Find the True entries

    The True values sit at positions 0, 2 and 3.

  3. 3
    Find the False entries

    The False values sit at positions 1, 4 and 5, which were removed.

  4. 4
    Map to names if you need them

    Use the same positions to look up the original column names in your own dataset, since the mask itself stores only True or False.

Result

Features at positions 0, 2 and 3 were kept, and features at positions 1, 4 and 5 were dropped.

A larger illustration uses a breast cancer dataset with 30 real features. Fifty columns of random noise are appended, so the input has 80 columns in total. Running SelectPercentile with percentile 50 keeps about half of them. The mask is then plotted as a single horizontal strip of 80 cells, in order, with black for True and white for False.

Reading that strip across, most of the original 30 features appear black, meaning kept, while most of the 50 noise columns appear white, meaning removed. The recovery is not perfect: some real features were dropped and some noise columns were kept. The strip is a visual reading aid, so when you need exact positions, go back to the Boolean mask values themselves.

Does Removing Features Improve a Model?

Removing features only matters if the model performs as well or better afterward, so the check has to be made explicitly. In the walkthrough, logistic regression is trained twice on the same train-test split: once on all features and once on only the selected features. Both models are then scored on the test set.

In that synthetic example the reduced feature set scored slightly higher. Removing the noise columns improved performance even though some genuine features were lost along the way. The walkthrough itself warns that this was a very simple synthetic setup and that results on real data are usually mixed.

Univariate selection remains useful in two situations. The first is when there are so many features that building a model on all of them is infeasible. The second is when you suspect that many features are completely uninformative. Outside those situations, the benefit is uncertain, and it can be small or absent.

QuestionSelectKBestSelectPercentile
What you specifyA fixed count k of featuresA fixed percentage from 0 to 100
Size when the dataset growsStays the sameGrows with the number of inputs
Best fitA downstream limit on input columnsOne pipeline that handles inputs of different widths

Two discarding rules that share the same scoring step but differ in how the kept set is sized

Where Judging Features One at a Time Goes Wrong

Because each feature is judged alone, the method can miss features that matter only in combination with other features. Two columns that are weak individually may be strong together, but the univariate test never asks how they interact. This is a limit of the method's design, not a bug in any one setting.

  • Common mistake

    Fitting the selector on the full dataset before splitting it

    What it looks like

    Calling fit on all rows, then splitting into training and test sets

    Why it fails

    The test rows influence which features are kept, so the test score is no longer an honest estimate.

    Do this instead

    Split the data first, fit the selector on the training split only, and transform both splits with that fitted selector.

  • Common mistake

    Assuming the mask lists feature names

    What it looks like

    Reading the mask as if it stores column names

    Why it fails

    The mask holds only True or False values, one per original position.

    Do this instead

    Pair each mask entry with its original position and look up the names in your own column list.

  • Common mistake

    Treating a fixed percentage as a fixed number of columns

    What it looks like

    Expecting 20 percent to keep the same count for every dataset

    Why it fails

    A percentage scales with the number of inputs, so the count changes as the width changes.

    Do this instead

    Compute the expected count from the actual number of input columns, or use SelectKBest if you need a fixed count.

  • Common mistake

    Discarding a feature because its individual p-value is high

    Why it fails

    A feature weak alone may matter in combination with another feature, and the univariate test cannot see that interaction.

    Do this instead

    Check the decision against the final model's performance rather than trusting the individual p-value alone.

Testing Your Reading of a Mask

EASY

A dataset has six input columns named age, income, zip_code, height, noise_1 and noise_2, in that order. After running SelectPercentile, get_support returns True, True, False, False, True, False. Which columns were kept, and which were dropped?

Hints
  • Pair each mask entry with its position first, starting from position 0.
  • The True entries are at positions 0, 1 and 4. Look up those positions in the column list.
  • Check your answer: kept columns are age, income and noise_1; dropped columns are zip_code, height and noise_2.

Key Takeaways for Using Univariate Selection

  1. 1
    Univariate feature selection tests each feature against the target on its own and removes features whose p-values are too high.
  2. 2
    SelectPercentile keeps a fixed share of the features, while SelectKBest keeps a fixed count.
  3. 3
    get_support returns a Boolean mask with one entry per original feature, and its positions map directly onto the input columns.
  4. 4
    Fit the selector on training data only, then transform both splits, and judge the benefit by comparing model performance rather than trusting one score.
  5. 5
    Selection helps most when the feature count is very large or many features are likely uninformative, and its benefit is uncertain on other data.

At a glance

  • Univariate feature selection tests each feature against the target on its own and removes features whose p-values are too high.
  • SelectPercentile keeps a fixed share of the features, while SelectKBest keeps a fixed count.
  • get_support returns a Boolean mask with one entry per original feature, and its positions map directly onto the input columns.
  • Fit the selector on training data only, then transform both splits, and judge the benefit by comparing model performance rather than trusting one score.
  • Selection helps most when the feature count is very large or many features are likely uninformative, and its benefit is uncertain on other data.

Related concepts

More concepts starting with U