Аналітики часто стикаються з викидами даних під час своєї роботи, наприклад під час аналізу AB-тесту, створення прогнозних моделей або відстеження тенденцій. Рішення зазвичай ґрунтуються на вибірковому середньому, яке дуже чутливе до викидів і може різко змінити значення. Отже, для прийняття правильного рішення вкрай важливо керувати викидами.
Розглянемо кілька простих і швидких підходів для роботи з незвичайними значеннями.
Уявіть, що вам потрібно провести експериментальний аналіз, використовуючи середнє значення замовлення як основний показник. Припустімо, що наша метрика зазвичай має нормальний розподіл. Крім того, ми знаємо, що розподіл показників у тестовій групі відрізняється від розподілу в контрольній. Іншими словами, середнє значення розподілу в контролі дорівнює 10, а в тесті – 12. Стандартне відхилення в обох групах дорівнює 3.
Однак обидва зразки мають викиди, які спотворюють середнє значення вибірки та стандартне відхилення вибірки.
import numpy as np N = 1000 mean_1 = 10 std_1 = 3 mean_2 = 12 std_2 = 3 x1 = np.concatenate((np.random.normal(mean_1, std_1, N), 10 * np.random.random_sample(50) + 20)) x2 = np.concatenate((np.random.normal(mean_2, std_2, N), 4 * np.random.random_sample(50) + 1))
Зверніть увагу , що розгляд метрики може мати викиди з обох сторін. Якби ваша метрика могла мати викиди лише з одного боку, методи можна було б легко трансформувати для цієї мети.
Найпростіший метод — обірвати всі спостереження до 5% процентиля та після 95% процентиля . У цьому випадку ми втратили 10% інформації як обман. Однак розподіли виглядають більш сформованими, а моменти вибірки ближче до моментів розподілу.
import numpy as np x1_5pct = np.percentile(x1, 5) x1_95pct = np.percentile(x1, 95) x1_cutted = [i for i in x1 if i > x1_5pct and i < x1_95pct] x2_5pct = np.percentile(x2, 5) x2_95pct = np.percentile(x2, 95) x2_cutted = [i for i in x2 if i > x2_5pct and i < x2_95pct]
Іншим способом є виключення спостережень за межами певного діапазону . Нижня смуга дорівнює 25% процентилю мінус половина інтерквартильного діапазону, а висока смуга дорівнює 75% процентилю плюс половина. Тут ми втратимо лише 0,7% інформації. Розподіл виглядає більш сформованим, ніж початковий. Вибіркові моменти ще більше дорівнюють моментам розподілу.
import numpy as np low_band_1 = np.percentile(x1, 25) - 1.5 * np.std(x1) high_band_1 = np.percentile(x1, 75) + 1.5 * np.std(x1) x1_cutted = [i for i in x1 if i > low_band_1 and i < high_band_1] low_band_2 = np.percentile(x2, 25) - 1.5 * np.std(x2) high_band_2 = np.percentile(x2, 75) + 1.5 * np.std(x2) x2_cutted = [i for i in x2 if i > low_band_2 and i < high_band_2]
Другий метод, який ми тут розглянули, це початкове завантаження. У цьому підході середнє будується як середнє підвибірок. У нашому прикладі середнє значення в контрольній групі дорівнює 10,35, а в досліджуваній групі – 11,78. Це все одно кращий результат порівняно з додатковою обробкою даних.
import pandas as pd def create_bootstrap_samples( sample_list: np.array, sample_size: int, n_samples: int ): # create a list for sample means sample_means = [] # loop n_samples times for i in range(n_samples): # create a bootstrap sample of sample_size with replacement bootstrap_sample = pd.Series(sample_list).sample(n = sample_size, replace = True) # calculate the bootstrap sample mean sample_mean = bootstrap_sample.mean() # add this sample mean to the sample means list sample_means.append(sample_mean) return pd.Series(sample_means) (create_bootstrap_samples(x1, len(x1), 1000).mean(), create_bootstrap_samples(x2, len(x2), 1000).mean())
Виявлення та обробка викидів важливі для прийняття правильного рішення. Тепер принаймні три швидкі та прості підходи можуть допомогти вам перевірити дані перед аналізом.
Однак важливо пам’ятати, що виявлені викиди можуть бути незвичними значеннями та ознакою ефекту новизни. Але це вже інша історія :)