Percentili in Python con NumPy
Calcola i percentili in Python con NumPy. Quartili, IQR per rilevare outlier, metodi di interpolazione e casi d'uso pratici nel ML.
Un percentile indica il valore al di sotto del quale cade una determinata percentuale di osservazioni nel dataset. Se uno studente si colloca all'80° percentile in un esame, l'80 % dei punteggi è inferiore al suo. I percentili sono un pilastro dell'analisi esplorativa dei dati e vengono utilizzati nel machine learning per il rilevamento di outlier, il clipping delle feature e la reportistica delle prestazioni del modello tra i sottogruppi.
Questo capitolo tratta:
- Cosa si intende per percentile e come viene calcolato
- Come usare
numpy.percentile()enumpy.quantile() - Quartili e il sommario a cinque numeri
- L'intervallo interquartile (IQR) per il rilevamento degli outlier
- Metodi di interpolazione e quando sono rilevanti
- Trovare il rango percentile di un valore specifico con SciPy
- Casi d'uso pratici nel ML: winsorizzazione e clipping dei dati
Cos'è un Percentile?
Un percentile divide un dataset ordinato in 100 parti uguali. Il P-esimo percentile è il valore al di sotto del quale (o uguale al quale) cade il P percento dei dati.
| Percentile | Nome comune | Significato |
|---|---|---|
| 25° | Q1 (primo quartile) | Il 25 % dei valori è al di sotto di questo punto |
| 50° | Q2 / Mediana | La metà dei valori è al di sotto di questo punto |
| 75° | Q3 (terzo quartile) | Il 75 % dei valori è al di sotto di questo punto |
| 90° | — | Il 90 % dei valori è al di sotto di questo punto |
I percentili sono strettamente correlati a media, mediana e moda: il 50° percentile corrisponde esattamente alla mediana.
Percentile vs. quantile
I due termini sono spesso usati in modo intercambiabile. Un quantile esprime la stessa idea usando una frazione da 0 a 1 invece di una percentuale da 0 a 100:
- Il 25° percentile = il quantile 0,25
- Il 75° percentile = il quantile 0,75
NumPy fornisce sia np.percentile() che np.quantile(). Si comportano in modo identico; scegli quello che rende il tuo codice più chiaro.
Calcolare un Percentile con NumPy
numpy.percentile(a, q) accetta un array-like a e un percentile q (0–100) e restituisce il valore interpolato in quella posizione.
Calcola il 75° percentile di un dataset
import numpy as np
data = [10, 20, 30, 40, 50]
result = np.percentile(data, 75)
print(result) # Output: 40.0Passa una lista a q per calcolare più percentili in una sola chiamata — NumPy li restituisce in un array:
Calcola il 25°, 50° e 75° percentile in una volta sola
import numpy as np
data = [10, 20, 30, 40, 50]
p25, p50, p75 = np.percentile(data, [25, 50, 75])
print(f'Q1 = {p25}') # Output: Q1 = 20.0
print(f'Q2 = {p50}') # Output: Q2 = 30.0
print(f'Q3 = {p75}') # Output: Q3 = 40.0Usare np.quantile()
np.quantile() accetta una frazione (0,0–1,0) invece di una percentuale:
Usa np.quantile() con un argomento frazionario
import numpy as np
data = [10, 20, 30, 40, 50]
q1 = np.quantile(data, 0.25)
q3 = np.quantile(data, 0.75)
print(f'Q1 = {q1}') # Output: Q1 = 20.0
print(f'Q3 = {q3}') # Output: Q3 = 40.0Quartili e il Sommario a Cinque Numeri
I tre quartili (Q1, Q2, Q3) insieme al minimo e al massimo formano il sommario a cinque numeri — un'istantanea compatta della distribuzione di qualsiasi dataset. Puoi calcolare tutti e cinque i valori con una singola chiamata:
Calcola il sommario a cinque numeri
import numpy as np
data = [10, 20, 30, 40, 50]
minimum, q1, median, q3, maximum = np.percentile(data, [0, 25, 50, 75, 100])
print(f'Min = {minimum}') # Output: Min = 10.0
print(f'Q1 = {q1}') # Output: Q1 = 20.0
print(f'Median = {median}') # Output: Median = 30.0
print(f'Q3 = {q3}') # Output: Q3 = 40.0
print(f'Max = {maximum}') # Output: Max = 50.0Il sommario a cinque numeri è la base di un box plot, che puoi disegnare con Matplotlib (vedi Istogrammi con Matplotlib per tecniche di visualizzazione correlate).
L'Intervallo Interquartile e il Rilevamento degli Outlier
L'intervallo interquartile (IQR) è la distanza tra Q1 e Q3:
IQR = Q3 − Q1Descrive la dispersione del 50 % centrale dei dati. Poiché ignora il quarto superiore e quello inferiore, l'IQR è robusto ai valori estremi — rendendolo lo strumento standard per il rilevamento degli outlier basato su regole.
La regola del recinto di Tukey segnala come potenziale outlier qualsiasi valore che superi di oltre 1,5 × IQR i limiti di ciascun quartile:
- Recinto inferiore: Q1 − 1,5 × IQR
- Recinto superiore: Q3 + 1,5 × IQR
Rileva gli outlier usando il metodo IQR
import numpy as np
data = [5, 7, 8, 9, 10, 11, 12, 13, 14, 80]
q1 = np.percentile(data, 25)
q3 = np.percentile(data, 75)
iqr = q3 - q1
lower_fence = q1 - 1.5 * iqr
upper_fence = q3 + 1.5 * iqr
outliers = [x for x in data if x < lower_fence or x > upper_fence]
print(f'Q1 = {q1}, Q3 = {q3}, IQR = {iqr}')
# Output: Q1 = 8.25, Q3 = 12.75, IQR = 4.5
print(f'Lower fence = {lower_fence}, Upper fence = {upper_fence}')
# Output: Lower fence = 1.5, Upper fence = 19.5
print(f'Outliers: {outliers}')
# Output: Outliers: [80]Il valore 80 è ben oltre il recinto superiore di 19,5, quindi viene segnalato come outlier. Il metodo IQR è ampiamente utilizzato perché non richiede alcuna assunzione sulla distribuzione dei dati sottostante.
Metodi di Interpolazione
Quando il percentile richiesto cade tra due punti del dataset, NumPy interpola. Il parametro method (aggiunto in NumPy 1.22, in sostituzione del vecchio parametro interpolation) controlla come viene effettuata l'interpolazione.
Confronta i metodi di interpolazione al 35° percentile
import numpy as np
data = [10, 20, 30, 40, 50]
# The 35th percentile falls between 20 (index 1) and 30 (index 2)
print(np.percentile(data, 35, method='linear')) # Output: 24.0 (default)
print(np.percentile(data, 35, method='lower')) # Output: 20
print(np.percentile(data, 35, method='higher')) # Output: 30
print(np.percentile(data, 35, method='midpoint')) # Output: 25.0
print(np.percentile(data, 35, method='nearest')) # Output: 20| Metodo | Descrizione | Quando usarlo |
|---|---|---|
linear | Media ponderata dei due valori circostanti | Predefinito; statisticamente più corretto |
lower | Restituisce il minore dei due valori circostanti | Quando sono richiesti indici interi |
higher | Restituisce il maggiore dei due valori circostanti | Limiti superiori conservativi |
midpoint | Media tra il valore inferiore e quello superiore | Reportistica semplice del punto medio |
nearest | Il punto dati effettivo più vicino | Quando il risultato deve essere un'osservazione reale |
Per la maggior parte delle analisi dei dati e del lavoro ML, il metodo predefinito linear è la scelta giusta.
Trovare il Rango Percentile di un Valore
A volte si pone la domanda inversa: dato un valore, a quale percentile corrisponde? Usa scipy.stats.percentileofscore():
Trova il rango percentile occupato da un valore specifico
from scipy import stats
data = [10, 20, 30, 40, 50]
rank = stats.percentileofscore(data, 30)
print(rank) # Output: 60.0
rank_of_25 = stats.percentileofscore(data, 25)
print(rank_of_25) # Output: 40.0Un punteggio di 30 si trova al 60° percentile — il che significa che il 60 % dei valori in data è uguale o inferiore a 30.
Caso d'Uso Pratico nel ML: Winsorizzazione
La winsorizzazione (chiamata anche clipping) limita i valori estremi a un confine percentile scelto invece di rimuoverli. Questo conserva il numero di righe riducendo al contempo l'influenza degli outlier sull'addestramento del modello.
Taglia gli outlier all'intervallo dal 10° al 90° percentile
import numpy as np
data = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 200]
lower = np.percentile(data, 10)
upper = np.percentile(data, 90)
clipped = np.clip(data, lower, upper)
print(f'Lower bound (10th): {lower}') # Output: Lower bound (10th): 20.0
print(f'Upper bound (90th): {upper}') # Output: Upper bound (90th): 100.0
print('Clipped:', list(clipped))
# Output: Clipped: [20.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0, 100.0]Entrambi i valori estremi — 10 (al di sotto del limite del 10° percentile pari a 20) e 200 (al di sopra del limite del 90° percentile pari a 100) — vengono portati al valore del recinto. La winsorizzazione è una fase di preprocessing comune prima dell'addestramento di modelli lineari o reti neurali, specialmente su dati finanziari o di sensori dove i valori estremi sono frequenti.
Per ulteriori informazioni sugli approcci di scaling delle feature che si affiancano al clipping basato sui percentili, consulta il capitolo Scale.
Riferimento Rapido
| Operazione | Funzione | Esempio |
|---|---|---|
| Percentile singolo | np.percentile(data, q) | np.percentile(data, 75) |
| Più percentili | np.percentile(data, [q1, q2, …]) | np.percentile(data, [25, 50, 75]) |
| Quantile (scala 0–1) | np.quantile(data, q) | np.quantile(data, 0.75) |
| Sommario a cinque numeri | np.percentile(data, [0,25,50,75,100]) | — |
| IQR | Q3 − Q1 | np.percentile(data, 75) - np.percentile(data, 25) |
| Rango percentile di un valore | scipy.stats.percentileofscore(data, v) | — |
| Taglia ai limiti percentile | np.clip(data, lower, upper) | np.clip(data, p10, p90) |
Argomenti Correlati
- Media, Mediana e Moda — misure di tendenza centrale; il 50° percentile è la mediana.
- Deviazione Standard — misura la dispersione attorno alla media; complementa l'IQR.
- Distribuzione dei Dati — comprendi asimmetria e outlier prima di scegliere le statistiche sommarie.
- Scale — tecniche di scaling delle feature per il preprocessing nel ML.
- Tutorial NumPy — competenze fondamentali di NumPy utilizzate in tutto questo capitolo.
Conclusione
I percentili classificano i valori all'interno di un dataset e ne rivelano la forma in modi che la media e la deviazione standard non possono. Con numpy.percentile(), il calcolo di Q1, Q2, Q3 e IQR richiede una singola riga di Python. Nel machine learning, i percentili compaiono in ogni fase: nell'analisi esplorativa dei dati per individuare gli outlier, nel preprocessing per winsorizzare i valori estremi e nella valutazione per comprendere l'accuratezza del modello sull'intera distribuzione dei dati. Padroneggiarlo ti fornisce uno strumento affidabile e privo di assunzioni che funziona su qualsiasi dataset indipendentemente dalla sua distribuzione.