← Назад к вопросам

Как работать с выбросами в данных? Какие методы обнаружения и обработки выбросов вы знаете?

2.2 Middle🔥 201 комментариев
#Python и инструменты#Статистика и математика

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Выбросы (Outliers): Обнаружение и обработка

Определение

Выброс (Outlier) — это значение, которое значительно отличается от остальных данных в наборе. Может быть результатом ошибки, особого события или подлинной аномалии.

Методы обнаружения выбросов

1. Метод трёх сигма (3-Sigma Rule)

Выброс = значение вне диапазона [mean - 3σ, mean + 3σ]

Пример:
Mean = 50, σ = 5
Нормальный диапазон: [35, 65]
Значение 100 → ВЫБРОС

SQL:

WITH stats AS (
    SELECT 
        AVG(value) as mean,
        STDDEV(value) as stddev
    FROM data
)
SELECT *
FROM data
WHERE value > (SELECT mean FROM stats) + 3 * (SELECT stddev FROM stats)
   OR value < (SELECT mean FROM stats) - 3 * (SELECT stddev FROM stats);

Плюсы: Простой, математичный, работает для нормального распределения Минусы: Не работает хорошо для асимметричных распределений

2. Метод IQR (Interquartile Range)

Q1 = 25-й процентиль
Q3 = 75-й процентиль
IQR = Q3 - Q1

Выброс = значение < Q1 - 1.5×IQR или > Q3 + 1.5×IQR

Пример:

Данные: [10, 12, 14, 16, 18, 20, 22, 100]

Q1 = 13, Q3 = 21, IQR = 8
Нижний порог = 13 - 1.5×8 = -3
Верхний порог = 21 + 1.5×8 = 33

Значение 100 > 33 → ВЫБРОС

SQL:

WITH quartiles AS (
    SELECT 
        PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY value) as q1,
        PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY value) as q3
    FROM data
)
SELECT *
FROM data
WHERE value < (SELECT q1 FROM quartiles) - 1.5 * ((SELECT q3 FROM quartiles) - (SELECT q1 FROM quartiles))
   OR value > (SELECT q3 FROM quartiles) + 1.5 * ((SELECT q3 FROM quartiles) - (SELECT q1 FROM quartiles));

Плюсы: Хорошо работает с асимметричными данными, робастный Минусы: Может пропустить мягкие выбросы

3. Метод процентилей

Выброс = значение < P5 или > P95
(или P1/P99, P10/P90 в зависимости от задачи)

Когда использовать: Когда нет нормального распределения

4. Z-score метод

z = (value - mean) / σ

Если |z| > 3 → выброс
(или > 2.5, > 2 в зависимости от чувствительности)

5. Локальный метод (DBSCAN, LOF)

Рассматривает соседние точки
Точка, окружённая непохожими значениями → выброс

Когда использовать: Когда есть кластеры в данных

Методы обработки выбросов

Способ 1: УДАЛИТЬ выброс

-- Удалить строки с выбросами
DELETE FROM data
WHERE value > mean + 3 * stddev
   OR value < mean - 3 * stddev;

Когда использовать:

  • Явная ошибка (отрицательная зарплата, дата рождения в будущем)
  • Данные от спама/ботов
  • Технический сбой

Плюсы: Простой Минусы: Теряем данные, может быть важно

Способ 2: ЗАМЕНИТЬ на другое значение

-- Заменить на mean
UPDATE data
SET value = (SELECT AVG(value) FROM data)
WHERE value > mean + 3 * stddev;

-- Заменить на median
UPDATE data
SET value = (SELECT PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY value) FROM data)
WHERE value > mean + 3 * stddev;

-- Заменить на Q3 (capping)
UPDATE data
SET value = (SELECT PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY value) FROM data)
WHERE value > mean + 3 * stddev;

Когда использовать:

  • Не хотим потерять строку
  • Есть частичные данные (например, покупки с датой, но без суммы)

Плюсы: Сохраняем данные Минусы: Может искажать распределение

Способ 3: ТРАНСФОРМАЦИЯ данных

import numpy as np

# Логарифмическая трансформация (для правого skew)
data_log = np.log(data)

# Box-Cox трансформация (автоматическая)
from scipy.stats import boxcox
data_transformed, lambda_param = boxcox(data)

# Квадратный корень
data_sqrt = np.sqrt(data)

SQL эквивалент:

SELECT 
    LN(value) as log_value,        -- натуральный логарифм
    SQRT(value) as sqrt_value
FROM data;

Когда использовать: Когда данные имеют skew (асимметричны)

Способ 4: WINDSORIZATION (обрезка)

Заменить экстремальные значения на граничные (P95, P99):

SELECT 
    CASE 
        WHEN value > PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY value) 
            THEN PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY value)
        WHEN value < PERCENTILE_CONT(0.05) WITHIN GROUP (ORDER BY value)
            THEN PERCENTILE_CONT(0.05) WITHIN GROUP (ORDER BY value)
        ELSE value
    END as windsorized_value
FROM data;

Когда использовать: Когда хотим сохранить данные, но ограничить влияние выбросов

Способ 5: ОТДЕЛЬНЫЙ АНАЛИЗ

Анализировать выбросы отдельно как группу:

-- Главная группа (без выбросов)
SELECT AVG(value) as avg_main
FROM data
WHERE value BETWEEN mean - 3*stddev AND mean + 3*stddev;

-- Выбросы (отдельно)
SELECT AVG(value) as avg_outliers, COUNT(*) as outlier_count
FROM data
WHERE value > mean + 3*stddev OR value < mean - 3*stddev;

Когда использовать: Выбросы имеют смысл (VIP клиенты, специальные события)

Практические примеры

Пример 1: Revenue данные

-- Часто VIP клиенты создают "выбросы"
-- Не удаляем, но анализируем отдельно

WITH revenue_stats AS (
    SELECT 
        AVG(total_spent) as mean_spent,
        STDDEV(total_spent) as stddev_spent
    FROM customers
)

SELECT 
    CASE 
        WHEN c.total_spent > (SELECT mean_spent FROM revenue_stats) + 3 * (SELECT stddev_spent FROM revenue_stats)
            THEN 'VIP (Outlier)'
        ELSE 'Regular'
    END as customer_segment,
    COUNT(*) as count,
    AVG(c.total_spent) as avg_spent
FROM customers c, revenue_stats
GROUP BY customer_segment;

Пример 2: Session Duration

-- Удалить явно ошибочные сессии (> 24 часов)
-- Windsorize остальные на 95-й процентиль

SELECT 
    CASE 
        WHEN duration > 24*60 THEN NULL  -- удалить очевидные ошибки
        WHEN duration > PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY duration)
            THEN PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY duration)
        ELSE duration
    END as clean_duration
FROM sessions;

Пример 3: A/B Тест с выбросами

-- Не удаляем выбросы, но делаем оба анализа:

-- Анализ 1: Все данные (robust к выбросам)
SELECT 
    test_group,
    PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY metric) as median_metric
FROM ab_test
GROUP BY test_group;

-- Анализ 2: Без выбросов (для проверки)
WITH stats AS (
    SELECT 
        AVG(metric) as mean,
        STDDEV(metric) as stddev
    FROM ab_test
)
SELECT 
    test_group,
    AVG(metric) as mean_metric
FROM ab_test
WHERE metric BETWEEN (SELECT mean - 3*stddev FROM stats) 
                  AND (SELECT mean + 3*stddev FROM stats)
GROUP BY test_group;

Как выбрать метод обработки?

1. ИССЛЕДУЙ выбросы
   - Реальны ли они? (VIP клиент = не выброс)
   - Ошибка данных? (удаль)
   - Техсбой? (удаль или windsorize)

2. УДАЛЯЙ если:
   - Явная ошибка (отрицательная цена)
   - Спам/бот
   - Ошибка ввода

3. ЗАМЕНЯЙ если:
   - Хочешь сохранить строку
   - Данные от реальных пользователей (но экстремальные)

4. ТРАНСФОРМИРУЙ если:
   - Асимметричное распределение
   - Логарифмическая связь в данных

5. АНАЛИЗИРУЙ ОТДЕЛЬНО если:
   - Выбросы имеют смысл (VIP, специальные события)
   - Нужно понять причину выбросов

Итог

Выбросы требуют внимания:

  • Обнаруживай через 3-sigma, IQR или процентили
  • Понимай причину выброса
  • Выбирай метод в зависимости от контекста
  • Документируй что делал и почему

Главное правило: Не игнорируй выбросы, разбирайся с ними!

Как работать с выбросами в данных? Какие методы обнаружения и обработки выбросов вы знаете? | PrepBro