Gli analisti spesso incontrano valori anomali nei dati durante il loro lavoro, come durante l'analisi AB-test, la creazione di modelli predittivi o il tracciamento di tendenze. Le decisioni si basano solitamente sulla media campionaria, che è molto sensibile ai valori anomali e può cambiare drasticamente il valore. Quindi, è fondamentale gestire i valori anomali per prendere la decisione corretta.
Consideriamo alcuni approcci semplici e rapidi per lavorare con valori insoliti.
Immagina di dover condurre un'analisi sperimentale usando un valore medio dell'ordine come metrica primaria. Diciamo che la nostra metrica ha solitamente una distribuzione normale. Inoltre, sappiamo che la distribuzione della metrica nel gruppo di prova è diversa da quella nel gruppo di controllo. In altre parole, la media della distribuzione nel gruppo di controllo è 10 e nel gruppo di prova è 12. La deviazione standard in entrambi i gruppi è 3.
Tuttavia, entrambi i campioni presentano valori anomali che alterano le medie e la deviazione standard del campione.
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 che la metrica considerata potrebbe avere valori anomali da entrambi i lati. Se la tua metrica potesse avere valori anomali solo da un lato, i metodi potrebbero essere facilmente trasformati per quello scopo.
Il metodo più semplice è quello di tagliare tutte le osservazioni prima del percentile del 5% e dopo il percentile del 95% . In questo caso, abbiamo perso il 10% delle informazioni come contro. Tuttavia, le distribuzioni sembrano più formate e i momenti campione sono più vicini ai momenti di distribuzione.
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]
Un altro modo è escludere le osservazioni al di fuori dell'intervallo specifico . La banda bassa è uguale al percentile del 25% meno la metà dell'intervallo interquartile, e la banda alta è uguale al percentile del 75% più la metà. Qui, perderemo solo lo 0,7% di informazioni. Le distribuzioni sembrano più formate di quelle iniziali. I momenti campione sono ancora più uguali ai momenti di distribuzione.
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]
Il secondo metodo che abbiamo preso in considerazione qui è un bootstrap. In questo approccio, la media è costruita come una media di sottocampioni. Nel nostro esempio, la media nel gruppo di controllo è uguale a 10,35 e nel gruppo di test è 11,78. È comunque un risultato migliore rispetto all'elaborazione dei dati aggiuntiva.
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())
Il rilevamento e l'elaborazione degli outlier sono importanti per prendere la decisione giusta. Ora, almeno tre approcci rapidi e diretti potrebbero aiutarti a controllare i dati prima dell'analisi.
Tuttavia, è essenziale ricordare che i valori anomali rilevati potrebbero essere valori insoliti e una caratteristica dell'effetto novità. Ma questa è un'altra storia :)