Misure di Posizione: Five-Number Summary, Outlier e Boxplot

Parte (2/2)

Potrebbe interessarti:

Il progetto Python, che comprende gli script mostrati in questo post, e quelli relativi alla creazione dei grafici Matplotlib, è disponibile assieme al corso Fondamenti di Statistica per il ML.

Dimmi di Più

Il Riassunto a Cinque Numeri (Five-Number Summary)

A partire dai quartili, è possibile ottenere informazioni importanti sia sulla posizione centrale sia sulla variabilità dei dati. In particolare:

  • il secondo quartile $Q2$ (mediana) rappresenta una misura di posizione centrale;
  • le differenze di $Q1$ e $Q3$ con la mediana $Q2$ descrivono la dispersione rispettivamente del secondo e del terzo quarto dei dati, cioè della parte centrale della distribuzione.

Tuttavia, i quartili, da soli, non forniscono informazioni sulla variabilità nelle code della distribuzione. Per completare l’analisi è quindi necessario considerare anche il valore minimo (Min) e il valore massimo (Max) del dataset. In questo modo è possibile misurare la dispersione:

  • nel primo quarto dei dati: $(Q1 - \text{Min})$;
  • nell’ultimo quarto dei dati: $(\text{Max} - Q2)$.

Il riassunto a cinque numeri (Five-Number Summary) di un dataset è quindi costituito dai seguenti valori:
$\text{Min},\; Q_1,\; Q_2,\; Q_3,\; \text{Max}$

Il Riassunto a Cinque Numeri

Essi stanno alla base della costruzione del boxplot, uno degli strumenti grafici più utilizzati per rappresentare in modo immediato la distribuzione dei dati, la variabilità e la presenza di eventuali outlier.

In Python possiamo calcolare il Five-Number Summary in questo modo:

import numpy as np

rng = np.random.default_rng(seed=42)

# Generazione di una distribuzione empirica approssimativamente gaussiana
n = 5_000
data = rng.normal(loc=100, scale=15, size=n)

# Calcolo dei quartili e dell'intervallo interquartile
Q1, Q2, Q3 = np.quantile(data, [0.25, 0.50, 0.75])
min = np.min(data)
max = np.max(data)
print("Riassunto a 5 numeri:")
print(f"Min: {min:.2f}")
print(f"Max: {max:.2f}")
print(f"Q1: {Q1:.2f}")
print(f"Q2: {Q2:.2f}")
print(f"Q3: {Q3:.2f}")

L’output è:

Min: 45.27
Max: 151.81
Q1: 89.62
Q2: 99.94
Q3: 109.47

Identificazione degli Outlier

Nell’analisi dei dati, l’identificazione degli outlier – cioè osservazioni che si discostano nettamente dal comportamento generale del dataset – è un passaggio importante. Questi valori richiedono sempre un’attenzione particolare, poiché possono avere origini diverse:

  • errori di misura o di registrazione;
  • osservazioni provenienti da popolazioni differenti;
  • valori estremi ma reali, che rappresentano fenomeni rari ma possibili.

Ad esempio:

Distribuzione con Outlier

E’ importante sottolineare che:

  • non tutte le osservazioni estreme sono outlier:
    in alcuni casi possono semplicemente riflettere una distribuzione asimmetrica (skewed), senza essere anomalie.

  • gli outlier non sono necessariamente “errori”:
    in molti contesti (finanza, medicina, controllo qualità) possono contenere informazioni preziose e indicare fenomeni rilevanti. Per questo motivo, la loro gestione deve essere sempre guidata da considerazioni statistiche e dal contesto applicativo.

Un esempio classico è la distribuzione della ricchezza individuale: patrimoni estremamente elevati (come quello di grandi imprenditori) risultano fortemente distanti dalla maggior parte dei valori e possono essere considerati outlier, pur essendo perfettamente validi.

Se l’outlier è chiaramente dovuto a un errore (di misura o di inserimento), può essere rimosso. Se invece non esiste una spiegazione evidente, la decisione se mantenerlo o meno richiede cautela, poiché la sua presenza può influenzare significativamente alcune misure statistiche (come la media e la deviazione standard).

Identificazione tramite Quartili e IQR

Uno dei metodi più utilizzati per individuare potenziali outlier si basa sui quartili e sull’intervallo interquartile (IQR):

$$ IQR = Q_3 - Q_1 $$

A partire da questi, si definiscono i cosiddetti limiti:

$$ \begin{align*} \text{Lower limit} & = Q_1 - 1.5 \cdot IQR\\ \text{Upper limit} & = Q_3 + 1.5 \cdot IQR\\ \end{align*} $$

Le osservazioni che sono inferiori al limite inferiore, oppure superano il limite superiore vengono considerate potenziali outlier.

Consideriamo un dataset in cui $Q1 = 46.76$ e $Q3 = 50.13$. L’intervallo interquartile risulta:

$$ IQR = Q_3 - Q_1 = 53.24 - 46.76 = 6.48 $$

A partire da questo valore, possiamo determinare i limiti per l’individuazione dei potenziali outlier:

$$ \begin{align*} \text{Lower limit} & = 46.76 - 1.5 \cdot 6.48 =37.04\\ \text{Upper limit} & = 53.24 + 1.5 \cdot 6.48= 62.96 \end{align*} $$

Di conseguenza:

  • tutte le osservazioni inferiori a $37.04$ sono considerate potenziali outlier inferiori;
  • tutte le osservazioni superiori a $62.96$ sono considerate potenziali outlier superiori:
Identificazione Outlier con Quartili e IQR

In Python:

import numpy as np

# Seed per riproducibilità
np.random.seed(42)

# Dati principali
n = 1000
data = np.random.normal(loc=50, scale=5, size=n)

# Outlier aggiunti
outliers = np.array([10, 15, 90, 95])

# Dataset completo
data_with_outliers = np.concatenate([data, outliers])

# Calcolo dei quartili e dell'intervallo interquartile
Q1, Q2, Q3 = np.quantile(data, [0.25, 0.50, 0.75])
IQR = Q3 - Q1

# Calcolo dei limiti
lower_limit = Q1 - 1.5 * IQR
upper_limit = Q3 + 1.5 * IQR

print(f"Q1: {Q1:.2f}")
print(f"Q2: {Q2:.2f}")
print(f"Q3: {Q3:.2f}")
print(f"IQR: {IQR:.2f}")
print(f"Lower limit: {lower_limit:.2f}")
print(f"Upper limit: {upper_limit:.2f}")

L’output è:

Q1: 46.76
Q2: 50.13
Q3: 53.24
IQR: 6.48
Lower limit: 37.05
Upper limit: 62.96

Effetto degli Outlier sulle Misure Statistiche

Quando un dataset contiene outlier o presenta una distribuzione asimmetrica (skewed), la scelta delle misure statistiche diventa particolarmente importante. In questi casi:

  • la mediana rappresenta una misura di posizione più robusta rispetto alla media;
  • l’intervallo interquartile (IQR) è una misura di dispersione più affidabile rispetto alla deviazione standard.

Questo accade perché media e deviazione standard utilizzano tutte le osservazioni, inclusi gli outlier, risultando quindi fortemente influenzate da valori estremi. Al contrario, mediana e IQR sono misure robuste, poiché si basano sulla posizione relativa dei dati e non risentono significativamente della presenza di valori anomali.

Il grafico sottostante confronta due distribuzioni: la prima senza outlier e la seconda con tre valori anomali. Nella seconda distribuzione possiamo osservare come gli outlier spostino la media verso la coda sinistra e aumentino la deviazione standard. Di conseguenza, l’intervallo $\mu \pm \sigma$, che rappresenta la dispersione dei dati intorno alla media, risulta sensibilmente più ampio:

Effetto degli Outlier sulle misure statistiche

In Python:

import numpy as np

# Dataset #1 e #2 con alcuni outlier
data1 = np.array([46, 47, 48, 48, 49, 49, 50, 50, 50, 51, 51, 52, 52, 53, 54])
data2 = np.concatenate((data1, [75, 85, 95]))
titles = ("Media, Mediana, Deviazione Standard e IQR",
          "Effetto degli Outlier su Media, Mediana, Deviazione Standard e IQR")

for i, (data, title) in enumerate(zip((data1, data2), titles)):
    # Calcolo delle statistiche
    mean = np.mean(data)
    median = np.median(data)
    std = np.std(data)
    q1 = np.percentile(data, 25)
    q3 = np.percentile(data, 75)
    iqr = q3 - q1

    print(f"[{title}]")
    print(f"Media: {mean:.1f}")
    print(f"Mediana: {median:.1f}")
    print(f"Deviazione standard: {std:.1f}")
    print(f"Q1: {q1:.1f}")
    print(f"Q3: {q3:.1f}")
    print(f"IQR: {iqr:.1f}\n")

L’output è:

[Media, Mediana, Deviazione Standard e IQR]
Media: 50.0
Mediana: 50.0
Deviazione standard: 2.2
Q1: 48.5
Q3: 51.5
IQR: 3.0

[Effetto degli Outlier su Media, Mediana, Deviazione Standard e IQR]
Media: 55.8
Mediana: 50.5
Deviazione standard: 13.6
Q1: 49.0
Q3: 52.8
IQR: 3.8

In sintesi, se i dati sono asimmetrici o contengono outlier:

  • usiamo la mediana come misura di posizione;
  • usiamo l’IQR come misura di dispersione;

Altrimenti, se i dati sono approssimativamente simmetrici e privi di outlier:

  • la media è una buona misura di posizione;
  • la deviazione standard è una misura adeguata della variabilità.

Il Grafico Boxplot

Il boxplot (box-and-whisker plot) è una rappresentazione grafica basata sul riassunto a cinque numeri e consente di visualizzare in modo immediato:

  • la posizione centrale dei dati;
  • la dispersione;
  • la forma della distribuzione (simmetria o asimmetria);
  • la presenza di outlier.

Per costruire un boxplot è utile introdurre il concetto di valori adiacenti, che sono le osservazioni più estreme che rimangono all’interno dei limiti definiti tramite IQR; cioè i valori più lontani che non sono considerati outlier. Se il dataset non contiene outlier, i valori adiacenti coincidono semplicemente con il valore minimo e massimo del dataset.

La costruzione di un boxplot avviene attraverso i seguenti passaggi:

  1. Calcoliamo i quartili.
  2. Individuaiamo i valori adiacenti e i potenziali outlier.
  3. Tracciamo un asse orizzontale su cui poter riportare i numeri ottenuti nei passaggi (1) e (2). Sopra questo asse, segnamo i quartili e i valori adiacenti con delle linee verticali.
  4. Uniamo i quartili per formare un rettangolo, quindi colleghiamo il rettangolo ai valori adiacenti con delle linee.
  5. Tracciamo una linea all’interno del box in corrispondenza della mediana .
  6. Segnamo ogni potenziale valore anomalo con un asterisco.

Ad esempio:

Distribuzione dati e confronto con Boxplot

Il boxplot fornisce numerose informazioni a colpo d’occhio:

  • la linea all’interno del box rappresenta la mediana;
  • gli estremi del box corrispondono a $Q1$ e $Q2$;
  • la lunghezza del box rappresenta l’intervallo interquartile (IQR);
  • i baffi si estendono fino ai valori adiacenti;
  • eventuali punti al di fuori dei baffi indicano degli outlier.

A differenza di altri grafici (come gli istogrammi), il boxplot non mostra la forma dettagliata della distribuzione, ma offre una sintesi compatta e robusta. Per questo motivo, è spesso utilizzato insieme ad altre rappresentazioni grafiche per un’analisi più completa dei dati.

In Python, tramite Matplotlib, possiamo disegnare un boxplot mediante la funzione Axes.boxplot:

import numpy as np
import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(12, 5))

# ...

# Creazione boxplot
ax.boxplot(data, vert=False, showfliers=False)

# Annotazioni quartili e mediana
q13_y, q2_y = 1.12, 0.84
ax.text(Q1, q13_y,  f"Q1", ha='left')
ax.text(Q2, q2_y, f"Q2", ha='left')
ax.text(Q3 - 0.4, q13_y,  f"Q3", ha='left')

# Valori adiacenti e annotazioni
IQR = Q3 - Q1
lower_limit = Q1 - 1.5 * IQR
upper_limit = Q3 + 1.5 * IQR
adjacent_lower = np.min(data[data >= lower_limit])
adjacent_upper = np.max(data[data <= upper_limit])
ax.text(adjacent_lower, 0.87, f"Val adiac inf", ha='center')
ax.text(adjacent_upper, 0.87, f"Val adiac sup", ha='center')
Caricamento
  • Rendering delle formule LaTeX...