Q&A library Python

How do I cap extreme values instead of deleting them in pandas?

Python Advanced clipoutlierswinsorising

Short answer

Use clip with a quantile as the bound to pull extreme values back to a threshold rather than removing the rows. This keeps the observations while limiting their influence, but it does change your data.

The short version

Use clip with a high quantile as the upper bound (and a low one as the lower). Extreme values are pulled back to the threshold rather than deleted, so you keep the rows but limit their influence. This is called winsorising. It is a deliberate alteration of your data and must be reported.

Capping at a percentile

import pandas as pd

s = pd.Series([1, 2, 100])

capped = s.clip(upper=s.quantile(0.9))
print(capped.round(1).tolist())   # [1.0, 2.0, 80.4]

The extreme 100 is pulled down to the 90th percentile. The row survives, but it can no longer dominate a mean or a regression.

Capping both ends

low, high = s.quantile([0.05, 0.95])
s.clip(lower=low, upper=high)

This is the usual symmetric form, trimming the most extreme few per cent at each end.

Why cap rather than drop

Dropping an outlier removes the observation entirely, which loses whatever else that row told you and reduces your sample. Capping keeps the row and its other columns, while stopping one wild value from dragging an average or a model fit. For a heavy-tailed measure where the extremes are real but not representative, capping is often the more honest compromise.

But be clear that it changes the data

Winsorising is not a neutral clean-up. It deliberately understates the true extremes, which means your maximum is no longer the real maximum and your variance is reduced. If those extremes are genuine and important (a real record-breaking value, a genuine failure), capping hides exactly the thing worth knowing.

So the decision rests on why the extreme exists. A data-entry error should be fixed or removed. A rare but real event should usually be kept as it is, and analysed with a method robust to it (a median, a rank-based test) rather than altered.

Always report it

If you winsorise, say so, and say at what thresholds. A summary statistic computed on capped data is not the same statistic, and a reader who assumes otherwise will draw the wrong conclusion. This is a matter of honesty, not just method.

Capping within groups

If groups have different scales, cap against each group's own quantiles, or a normal value in one group will be clipped against another group's range.

df["capped"] = df.groupby("city")["amount"].transform(
    lambda x: x.clip(upper=x.quantile(0.95))
)

The alternatives worth considering first

Before altering values, consider whether a more robust statistic answers your question without touching the data: the median instead of the mean, the interquartile range instead of the standard deviation, or a rank-based test instead of a t-test. These handle outliers by design, with no need to change what you observed, which is usually the cleaner path.

Need this solved on your own data?

The library is free and always will be. When the problem is bigger than an answer, we take on the work.

Start a project