3 минут чтения
24 марта 2021 г.
Обнаружение статистических выбросов в Python
Параллельно с выходом материала «Обнаружение выбросов в R» предлагаем посмотреть, как те же методы обнаружения выбросов реализовать в Python.
Данные
Для наглядности эксперимента возьмём тот же пакет данных mpg — скачать его в виде csv-таблицы можно с GitHub. Импортируем библиотеки и читаем таблицу в DataFrame:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
df = pd.read_csv(‘mpg.csv’)
Минимальные и максимальные значения
Тут всё просто. Выводим описание всего датасета методом describe():
df.describe()
Гистограмма
Такой график тоже можно построить в одну строку, используя внутренние средства библиотеки pandas:
df.hwy.plot(kind=’hist’, density=1, bins=20, stacked=False, alpha=.5, color=’grey’)
Box plot
В случае ящика с усами далеко идти тоже не приходится — в pandas есть метод и для этого:
_, bp = df.hwy.plot.box(return_type=’both’)
Получим точки с графика и выведем их в таблице, используя объект bp:
outliers = [flier.get_ydata() for flier in bp[«fliers»]][0]
df[df.hwy.isin(outliers)]
Процентили
При помощи метода quantile получаем соответствующую нижнюю и верхнюю границы, а затем выводим всё, что выходит за их рамки:
lower_bound = df.hwy.quantile(q=0.025)
upper_bound = df.hwy.quantile(q=0.975)
df[(df.hwy < lower_bound) | (df.hwy > upper_bound)
Фильтр Хэмпеля
Мы используем реализацию фильтра Хэмпеля, найденную на StackOverflow
Опишем функцию, которая заменяет на nan все значения, у которых разница с медианой больше, чем три медианных абсолютных отклонения.
def hampel(vals_orig):
vals = vals_orig.copy()
difference = np.abs(vals.median()-vals)
median_abs_deviation = difference.median()
threshold = 3 * median_abs_deviation
outlier_idx = difference > threshold
vals[outlier_idx] = np.nan
return(vals)
И применим к нашему набору данных:
hampel(df.hwy)0 29.0
1 29.0
2 31.0
3 30.0
4 26.0
…
229 28.0
230 29.0
231 26.0
232 26.0
233 26.0
Name: hwy, Length: 234, dtype: float64
В выводе нет nan-значений, а значит и выбросов фильтр Хэмпеля не обнаружил.
Тест Граббса
Автор реализации теста Граббса и теста Рознера для Python
Опишем три функции: первая находит значение критерия Граббса и максимальное значение в наборе данных, вторая — критическое значение с учётом объёма выборки и уровня значимости, а третья проверяет, является ли значение с максимальным индексом выбросом:
import numpy as np
from scipy import stats
def grubbs_stat(y):
std_dev = np.std(y)
avg_y = np.mean(y)
abs_val_minus_avg = abs(y — avg_y)
max_of_deviations = max(abs_val_minus_avg)
max_ind = np.argmax(abs_val_minus_avg)
Gcal = max_of_deviations / std_dev
print(f»Grubbs Statistics Value: {Gcal}»)
return Gcal, max_ind
def calculate_critical_value(size, alpha):
t_dist = stats.t.ppf(1 — alpha / (2 * size), size — 2)
numerator = (size — 1) * np.sqrt(np.square(t_dist))
denominator = np.sqrt(size) * np.sqrt(size — 2 + np.square(t_dist))
critical_value = numerator / denominator<br>
print(f»Grubbs Critical Value: {critical_value}»)
return critical_value
def check_G_values(Gs, Gc, inp, max_index):
if Gs > Gc:
print(f»{inp[max_index]} is an outlier»)
else:
print(f»{inp[max_index]} is not an outlier»)
Заменим значение в 34 строке на 212:
df.hwy[34] = 212
И выполним три функции:
Gcritical = calculate_critical_value(len(df.hwy), 0.05)
Gstat, max_index = grubbs_stat(df.hwy)
check_G_values(Gstat, Gcritical, df.hwy, max_index)
Grubbs Critical Value: 3.652090929984981
Grubbs Statistics Value: 13.745808761040397
212 is an outlier
Тест Рознера
Для теста Рознера достаточно дописать одну функцию, которая принимает набор данных, уровень значимости и число потенциальных выбросов:
def ESD_test(input_series, alpha, max_outliers):
for iteration in range(max_outliers):
Gcritical = calculate_critical_value(len(input_series), alpha)
Gstat, max_index = grubbs_stat(input_series)
check_G_values(Gstat, Gcritical, input_series, max_index)
input_series = np.delete(input_series, max_index)
Используя функцию на нашем наборе данных получаем, что значение 212 является выбросом, а 44 – нет:
ESD_test(np.array(df.hwy), 0.05, 3)
Grubbs Critical Value: 3.652090929984981
Grubbs Statistics Value: 13.745808761040408
212 is an outlier
Grubbs Critical Value: 3.6508358337727187
Grubbs Statistics Value: 3.455960616168714
44 is not an outlier
Grubbs Critical Value: 3.649574509044683
Grubbs Statistics Value: 3.5561478280392245
44 is not an outlier
[ Рекомендации ]
Читайте также
[ Связаться ]
Давайте раскроем потенциал вашего бизнеса вместе
Заполните форму на бесплатную консультацию