Как убрать выбросы в pandas
Карьерник — квиз-тренажёр в Telegram с 1500+ вопросами для собесов аналитика. SQL, Python, A/B, метрики. Бесплатно.
Зачем это нужно
Выбросы — головная боль любого аналитика. Один клиент с покупкой на миллион искажает средний чек всей базы в 3 раза. 10 тестовых аккаунтов внутри команды ломают DAU. Чек 100 000 ₽ оказывается опечаткой кассира. Не обработали — сделали неверные выводы.
На собеседовании вопрос про outliers классический: «как найти и обработать?». Правильный ответ включает несколько методов — IQR, Z-score, percentile — и понимание, когда какой уместен. Плюс обязательно обсудить, нужно ли вообще удалять или это реальный сигнал.
В статье:
- 3 метода детектирования (IQR, Z-score, percentile)
- Winsorize как альтернатива удалению
- Log-трансформация
- Когда удалять, когда оставить
- Код pandas для всех методов
1. Метод IQR (Inter-Quartile Range)
Самый робастный:
import pandas as pd
Q1 = df['amount'].quantile(0.25)
Q3 = df['amount'].quantile(0.75)
IQR = Q3 - Q1
lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR
# пометить выбросы
df['is_outlier'] = (df['amount'] < lower) | (df['amount'] > upper)
# удалить
df_clean = df[(df['amount'] >= lower) & (df['amount'] <= upper)]Коэффициент 1.5 — стандарт. Для более строгого — 3.0.
2. Z-score
import numpy as np
z = (df['amount'] - df['amount'].mean()) / df['amount'].std()
df['is_outlier'] = np.abs(z) > 3 # >3 SD от mean
df_clean = df[np.abs(z) <= 3]Минус: сам mean и std зависят от outliers. IQR более надёжен.
3. Percentile
Прагматично: «топ 1% — выбросы»:
lower = df['amount'].quantile(0.01)
upper = df['amount'].quantile(0.99)
df_clean = df[(df['amount'] >= lower) & (df['amount'] <= upper)]Или только с одной стороны:
# только big outliers
upper = df['amount'].quantile(0.99)
df_clean = df[df['amount'] <= upper]4. Winsorize — не удалять, а «обрезать»
Заменяет экстремальные значения на границу (не удаляет строки):
from scipy.stats.mstats import winsorize
df['amount_winsorized'] = winsorize(df['amount'], limits=[0.01, 0.01])Значения ниже P1 → P1. Выше P99 → P99. Сохраняет структуру, но смягчает хвосты.
5. Log-трансформация
Для данных с тяжёлым хвостом (revenue, время):
import numpy as np
df['amount_log'] = np.log1p(df['amount']) # log(1+x) — safe для 0Не убирает outliers, но делает их менее влиятельными. Хорошо для ML.
6. Multi-variate outliers
Один признак normal, но комбинация странная. Нужны ML-методы:
from sklearn.ensemble import IsolationForest
iso = IsolationForest(contamination=0.01)
df['is_outlier'] = iso.fit_predict(df[['amount', 'items_count']]) == -17. Per-group outliers
Outliers относительно группы, не глобально:
def detect_outliers(group):
Q1 = group.quantile(0.25)
Q3 = group.quantile(0.75)
IQR = Q3 - Q1
return (group < Q1 - 1.5*IQR) | (group > Q3 + 1.5*IQR)
df['is_outlier'] = df.groupby('category')['amount'].transform(detect_outliers)«Выброс в Electronics» ≠ «выброс в Grocery» — разные масштабы.
8. Visualize перед удалением
import seaborn as sns
sns.boxplot(x=df['amount']) # видно outliers как точкиИли histogram:
df['amount'].hist(bins=100)Часто сразу становится понятно, настоящий ли outlier.
Когда НЕ удалять
1. Outlier — реальный сигнал
Whale-клиент дал 80% выручки. Удалять его = лгать.
2. Финансовые метрики
Для revenue total — все значения нужны.
3. ML для extreme cases
Обучаете model fraud detection — outliers это то, что нужно поймать.
4. Без понимания причины
Сначала выясните, почему outlier. Если баг — исправить в источнике. Если реальный — оставить.
Когда удалить / обработать
- Opecatka в данных (миллион вместо тысячи)
- Test / internal accounts
- Boт / фрод
- Для «типичного» описания
Для A/B-тестов
В A/B с тяжёлым хвостом (чек, session length) outliers искажают результат:
- Winsorize перед тестом (P99 → P99)
- Mann-Whitney вместо t-test
- Bootstrap для CI
Частые ошибки
1. Удалить outliers безальтернативно
«Удалил, среднее стало красивее». Потеряли информацию о реальном business.
2. Z-score на non-normal
Если данные скошены (lognormal), Z-score даёт неверные outliers.
3. Удалять по «круглым» числам
«Чек > 100 000 → выброс». Почему 100 000? Обоснуйте.
4. Не документировать
Через месяц никто не вспомнит, почему 200 записей удалено.
Связанные темы
FAQ
Какой метод лучше?
IQR для одномерных. Isolation Forest для многомерных.
Удалять или winsorize?
Winsorize сохраняет строки, меняет только extreme значения. Обычно предпочтительно.
Для ML — обрабатывать outliers?
Зависит от модели. Tree-based устойчивы. Linear — нет, надо.
В A/B обязательно?
Для heavy-tailed метрик — да.
Тренируйте pandas — откройте тренажёр с 1500+ вопросами для собесов.