Distribuzione normale: definizione e verifica di normalità

Distribuzione normale

Molto spesso nell’analisi dei dati sentiamo parlare di distribuzione normale e di ipotesi di normalità sul campione dei dati. Per definizione una variabile quantitativa continua X segue una distribuzione normale con media μ e deviazione standard σ se

Non spaventarti se questa formula ti appare difficile! In questo articolo ti spiegherò il suo significato e come riconoscere se un campione di dati proviene da una popolazione normale con l’aiuto del linguaggio Python.

Definizione distribuzione normale

Iniziamo a interpretare la formula matematica vista sopra. La funzione f(x) è l’usuale funzione il cui grafico ha la forma “a campana”. Sono sicuro che l’avrai già vista almeno qualche altra volta! La parte in alto della formula ci dice che la probabilità che la variabile X assuma un valore tra due numeri a e b è uguale al relativo integrale definito della funzione f(x). Ma l’integrale non è nient’altro che l’area tra il grafico della funzione è l’asse x.

Ad esempio, dall’immagine in basso deduciamo che la probabilità che la variabile X sia compresa tra -1 e 1 è pari all’area della parte di grafico colorata in rosa chiaro.

Grafico a campana della curva normale e calcolo della probabilità come area

Nella pratica non ci sarà bisogno di calcolare questa area con qualche formula strana o ancor peggio risolvendo l’integrale, ci penserà un linguaggio di programmazione come Python a farlo al posto nostro!

Verificare la normalità di una popolazione

In moltissime applicazioni della statistica inferenziale sarà necessario verificare che i nostri dati seguano la distribuzione normale. In realtà questa affermazione non è propriamente corretta dal punto di vista lessicale. Quando facciamo analisi statistica abbiamo a disposizione solo un campione finito di dati, ricordiamo invece che il compito della statistica inferenziale è generalizzare le nostre osservazioni all’intera popolazione. Ciò che impareremo a dimostrare sarà dunque se il campione proviene da una popolazione con distribuzione normale. Il soggetto della verifica è dunque la popolazione di partenza, non il campione, per quanto poi nella pratica abbiamo a disposizione solo quest’ultimo.

In generale abbiamo diversi metodi per verificare la normalità di una popolazione. Nessuno tra questi è migliore degli altri o sufficiente da solo per arrivare a una risposta definitiva. Un’indagine statistica scrupolosa estrae una risposta significativa soltanto condensando le osservazioni derivanti da più tipologie di analisi! In questo articolo presenteremo questi quattro metodi:

  • disegno dell’istogramma;
  • calcolo degli indici di asimmetria di Fisher e Curtosi;
  • utilizzo del q-q plot;
  • test di Shapiro – Wilk.

Analisi della normalità sulla base dell’istogramma

Partiamo importando con la libraria Pandas di Python una serie di misurazioni della temperatura, disponibili su un mio repository di Github

import pandas as pd
d1 = pd.read_csv("https://raw.githubusercontent.com/iantomasinicola/Esercizi/main/Dati_test_normalita.csv") 
d1.head(5)

A questo punto possiamo disegnare un istogramma con l’aiuto della libreria seaborn e verificare se la forma ottenuta è simile a quella della funzione f(x) vista nel paragrafo precedente.

import seaborn as sns
sns.histplot(data=d1["Temperatura"],kde=True) 
creazione di un'istogramma per verificare la normalità di una distribuzione

In questo caso otteniamo un risultato molto soddisfacente, notiamo infatti che:

  • il grafico ha un solo picco (questa probabilmente è una delle verifiche più importanti che possiamo fare con l’istogramma);
  • il picco si trova in una posizione abbastanza centrale;
  • i rettangoli tendono a decrescere in altezza man mano che ci si sposta dal picco centrale;
  • la linea del grafico ottenuta grazie al parametro kde ricorda il grafico di f(x);
  • non sono presenti rettangoli in valori estremi e “fuori scala”, quindi non sono stati rilevati outlier.

Tutte queste osservazioni indirizzano la nostra tesi nel sostenere che il campione di dati provenga da una popolazione normale, ma da sole non bastano! Esistono casi (anche abbastanza frequenti) in cui i dati hanno un’istogramma che ricorda molto da vicino la forma a campana, ma non si tratta di una distribuzione normale. Un po’ più raro invece è il caso contrario: se l’istogramma è molto lontano dalla forma cercata, allora è difficile (ma comunque non impossibile) che la popolazione sia normale.

Calcolo degli indici di forma

Le distribuzioni normali sono caratterizzate dai seguenti valori per gli indici di forma:

  • indice di asimmetria di Fisher pari a zero;
  • indice di curtosi pari a zero (o pari a 3 in base alla formula utilizzata).

Un’idea per verificare la normalità è dunque calcolare questi due indici e valutare se il loro valore è prossimo allo zero. Facciamolo sempre con Python, ma questa volta con l’ausilio della libreria scipy

from scipy import stats
stats.skew(d1["Temperatura"],bias=False)
stats.kurtosis(d1["Temperatura"],bias=False)

Nel nostro caso otteniamo i valori 0.17 e -0.13: ottimo, sono davvero vicini allo zero! La prossima domanda sarà abbastanza spontanea: qual è la soglia per stabilire se questi valori sono abbastanza prossimi allo zero? Purtroppo non può esserci una risposta precisa, in questo post trovi una lunga discussione a riguardo https://www.researchgate.net/post/What_is_the_acceptable_range_of_skewness_and_kurtosis_for_normal_distribution_of_data

A mio parere, in generale la risposta è dipende, sia dai risultati delle altre tipologie di analisi e sia dal motivo per cui si sta cercando di dimostrare la normalità della popolazione. Comunque, per dare qualche punto di riferimento, abbastanza spesso può essere ragionevole considerare gli intervalli (-1,1) o (-2,2).

corso di analisi dei dati
Visita la mia piattaforma didattica realizzata con l’obiettivo di creare un percorso unico e completo nella formazione per Data Analyst.

Utilizzo del q-q plot

Il q-q plot è un metodo grafico più generale che permette di confrontare due generiche distribuzioni di dati. Consiste nel riportare su un grafico i punti che hanno:

  • come ascissa un percentile della prima distribuzione;
  • come ordinata il medesimo percentile della seconda distribuzione.

Se le due distribuzioni sono identiche, allora ovviamente lo saranno anche tutti i relativi percentili. Il grafico ottenuto tramite il q-q plot sarà quindi una linea diagonale, inclinata di 45 gradi (la bisettrice del primo e terzo quadrante). Analizzando quanto il q-q plot ottenuto si discosti dalla bisettrice, abbiamo un’idea di quanto siano simili le due distribuzioni coinvolte.

Nel nostro contesto, l’idea è quella di utilizzare il q-q plot considerando una normale come una delle due distribuzioni. I percentili delle normali possono essere calcolati tramite una formula matematica, implementata nel metodo norm.ppf di Scipy. Ad esempio, per calcolare il trentesimo percentile di una variabile normale con media 0 e deviazione standard 1, scriveremo

from scipy import stats
stats.norm.ppf(q=0.30, loc=0, scale=1)

Tramite un ciclo for posso facilmente calcolare tutti i percentili e inserire i dati ottenuti in un Dataframe di Pandas:

percentili_normale = []
for i in range(1,100):
    percentili_normale.append(stats.norm.ppf(q=i/100, loc=0, scale=1))
df_q = pd.Dataframe(data=percentili_normale, columns = ["Normale"])

Analogamente potrò calcolare i percentili dei miei dati di partenza standardizzati (in modo da avere media uguale a 0 e deviazione standard uguale a 1 come la normale presa a riferimento)

d1["Temperatura_s"] = (d1["Temperatura"]-d1["Temperatura"].mean())/d1["Temperatura"].std(ddof=0)
percentili = []  
for i in range(1,100):
    percentili.append(d1["Temperatura_s"].quantile(i/100)) 
   
df_q["Temperatura_s"]=percentili

A questo punto per ottenere il q-q plot mi basterà costruire un grafico di dispersione sulle due colonne del DataFrame, con l’aiuto di Seaborn

import seaborn as sns
g = sns.scatterplot(data = df_q,
                               x = "Normale",
                               y = "Temperatura_s")

Ecco il grafico che ho ottenuto, direi molto fedele alla bisettrice del primo e terzo quadrante!

Test di Shapiro-Wilk

Eseguire un test statistico di Shapiro-Wilk è uno dei modi migliori per testare la normalità della popolazione statistica studiata. I risultati del test sono affidabili però solo se il campione non è eccessivamente grande. Indicativamente non dovrà essere composto da più di 3000 unità (come al solito non si tratta di un numero fisso, in alcuni testi ad esempio è riportato il valore 5000).

Le ipotesi del test di Shapiro Wilk sono:

  • H0: il campione proviene da una popolazione con distribuzione normale
  • H1: il campione non proviene da una popolazione con distribuzione normale

Possiamo eseguire il test con la libreria scipy, utilizzando il metodo stats.shapiro che ci darà in output il risultato della statistica test e il p-value

from scipy import stats
stats.shapiro(d1["Temperatura"].values)

In questo caso otteniamo un p-value molto alto 0.74, ampiamente sufficiente per non rifiutare l’ipotesi H0 per cui il campione proviene da una popolazione normale.

Continua a imparare

Torna in alto
Torna su