Analitycy często napotykają wartości odstające w danych podczas swojej pracy, np. podczas analizy testów AB, tworzenia modeli predykcyjnych lub śledzenia trendów. Decyzje są zazwyczaj podejmowane na podstawie średniej próby, która jest bardzo wrażliwa na wartości odstające i może drastycznie zmienić wartość. Dlatego kluczowe jest zarządzanie wartościami odstającymi, aby podjąć właściwą decyzję.
Rozważmy kilka prostych i szybkich podejść do pracy z nietypowymi wartościami.
Wyobraź sobie, że musisz przeprowadzić analizę eksperymentu, używając średniej wartości zamówienia jako podstawowej metryki. Załóżmy, że nasza metryka ma zwykle rozkład normalny. Wiemy również, że rozkład metryki w grupie testowej różni się od rozkładu w grupie kontrolnej. Innymi słowy, średnia rozkładu w grupie kontrolnej wynosi 10, a w grupie testowej 12. Odchylenie standardowe w obu grupach wynosi 3.
Jednakże obie próbki mają obserwacje odstające, które zaburzają średnie próby i odchylenie standardowe próby.
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))
NB , że rozważanie metryki może mieć wartości odstające z obu stron. Jeśli Twoja metryka może mieć wartości odstające tylko z jednej strony, metody można łatwo przekształcić w tym celu.
Najprostszą metodą jest odcięcie wszystkich obserwacji przed 5% percentylem i po 95% percentylu . W tym przypadku straciliśmy 10% informacji jako oszustwo. Jednak rozkłady wyglądają na bardziej uformowane, a momenty próby są bliższe momentom rozkładu.
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]
Innym sposobem jest wykluczenie obserwacji spoza określonego zakresu . Dolny pas jest równy 25% percentyla minus połowa zakresu interkwartylowego, a górny pas jest równy 75% percentyla plus połowa. Tutaj stracimy tylko 0,7% informacji. Rozkłady wyglądają na bardziej uformowane niż początkowe. Momenty próbki są jeszcze bardziej równe momentom rozkładu.
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]
Drugą metodą, którą rozważamy tutaj, jest bootstrap. W tym podejściu średnia jest konstruowana jak średnia podpróbek. W naszym przykładzie średnia w grupie kontrolnej wynosi 10,35, a w grupie testowej 11,78. Nadal jest to lepszy wynik w porównaniu z dodatkowym przetwarzaniem danych.
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())
Wykrywanie i przetwarzanie wartości odstających ma duże znaczenie dla podejmowania właściwych decyzji. Teraz przynajmniej trzy szybkie i proste podejścia mogą pomóc Ci sprawdzić dane przed analizą.
Należy jednak pamiętać, że wykryte wartości odstające mogą być nietypowymi wartościami i cechą efektu nowości. Ale to już inna historia :)