È sempre una buona idea esaminare i nostri dati prima di iniziare a tracciare. Possiamo leggere i dati in un dataframe pandas e visualizzare le prime 10 righe:

import pandas as pd# Read in data and examine first 10 rows
flights = pd.read_csv('data/formatted_flights.csv')
flights.head(10)
Capo del dataframe

I ritardi di arrivo dei voli sono in minuti e valori negativi significano che il volo era in anticipo (si scopre che i voli tendono spesso ad arrivare in anticipo, solo mai quando ci siamo noi!) Ci sono oltre 300.000 voli con un ritardo minimo di -60 minuti e un ritardo massimo di 120 minuti. L’altra colonna nel dataframe è il nome della compagnia aerea che possiamo usare per i confronti.

Un ottimo modo per iniziare ad esplorare una singola variabile è l’istogramma. Un istogramma divide la variabile in bins, conta i punti dati in ogni bin e mostra i bins sull’asse delle x e i conteggi sull’asse delle y. Nel nostro caso, i bin saranno un intervallo di tempo che rappresenta il ritardo dei voli e il conteggio sarà il numero di voli che rientrano in quell’intervallo. La larghezza di banda è il parametro più importante per un istogramma e dovremmo sempre provare alcuni valori diversi di larghezza di banda per selezionare quello migliore per i nostri dati.

Per fare un istogramma di base in Python, possiamo usare sia matplotlib che seaborn. Il codice qui sotto mostra le chiamate di funzione in entrambe le librerie che creano figure equivalenti. Per le chiamate di plot, specifichiamo la larghezza dei bin per il numero di bins. Per questa trama, userò dei bins di 5 minuti di lunghezza, il che significa che il numero di bins sarà l’intervallo dei dati (da -60 a 120 minuti) diviso per la larghezza del bin, 5 minuti ( bins = int(180/5)).

Histogramma (figura equivalente prodotta sia da matplotlib che da seaborn)

Per gli istogrammi più basilari, Io andrei con il codice di matplotlib perché è più semplice, ma useremo la funzione seaborn distplot più avanti per creare diverse distribuzioni ed è bene avere familiarità con le diverse opzioni.

Come sono arrivato a 5 minuti per la larghezza dei bin? L’unico modo per capire un binwidth ottimale è provare più valori! Qui sotto c’è il codice per fare la stessa figura in matplotlib con una serie di valori di larghezza di banda. In definitiva, non c’è una risposta giusta o sbagliata alla larghezza di banda, ma ho scelto 5 minuti perché penso che rappresenti meglio la distribuzione.

Iistogrammi con diverse larghezze di banda

La scelta della larghezza di banda influenza significativamente il grafico risultante. Una larghezza di banda più piccola può rendere il grafico disordinato, ma una larghezza di banda più grande può oscurare le sfumature dei dati. Matplotlib sceglierà automaticamente una larghezza di banda ragionevole per voi, ma a me piace specificare la larghezza di banda da solo dopo aver provato diversi valori. Non c’è una vera risposta giusta o sbagliata, quindi provate alcune opzioni e vedete quale funziona meglio per i vostri dati particolari.

Quando gli istogrammi falliscono

Gli istogrammi sono un ottimo modo per iniziare ad esplorare una singola variabile tratta da una categoria. Tuttavia, quando vogliamo confrontare le distribuzioni di una variabile attraverso più categorie, gli istogrammi hanno problemi di leggibilità. Per esempio, se vogliamo confrontare le distribuzioni dei ritardi di arrivo tra compagnie aeree, un approccio che non funziona bene è quello di creare istogrammi per ogni compagnia aerea sullo stesso grafico:

Iistogrammi sovrapposti con più compagnie aeree

(Si noti che l’asse y è stato normalizzato per tenere conto del diverso numero di voli tra le compagnie aeree. Per fare questo, passate l’argomento norm_hist = True alla chiamata della funzione sns.distplot.)

Questo grafico non è molto utile! Tutte le barre che si sovrappongono rendono quasi impossibile fare confronti tra le compagnie aeree. Vediamo alcune possibili soluzioni a questo problema comune.

Soluzione #1: Istogrammi affiancati

Invece di sovrapporre gli istogrammi delle compagnie aeree, possiamo metterli fianco a fianco. Per fare questo, creiamo una lista dei ritardi di arrivo per ogni compagnia aerea, e poi la passiamo nella chiamata della funzione plt.hist come una lista di liste. Dobbiamo specificare diversi colori da usare per ogni compagnia aerea e un’etichetta in modo da poterli distinguere. Il codice, compresa la creazione delle liste per ogni compagnia aerea è qui sotto:

Di default, se passiamo una lista di liste, matplotlib metterà le barre affiancate. Qui, ho cambiato la larghezza dei bin a 15 minuti perché altrimenti il grafico è troppo ingombrante, ma anche con questa modifica, questo non è un dato efficace. Ci sono troppe informazioni da elaborare in una volta sola, le barre non si allineano con le etichette, ed è ancora difficile confrontare le distribuzioni tra le linee aeree. Quando facciamo un grafico, vogliamo che sia il più facile possibile da capire per l’osservatore, e questa figura non soddisfa questo criterio! Guardiamo una seconda potenziale soluzione.

Soluzione #2: barre impilate

Invece di tracciare le barre per ogni compagnia aerea fianco a fianco, possiamo impilarle passando il parametro stacked = True alla chiamata dell’istogramma:

# Stacked histogram with multiple airlines
plt.hist(, bins = int(180/15), stacked=True,
normed=True, color = colors, label=names)

Bene, questo non è affatto meglio! Qui, ogni compagnia aerea è rappresentata come una sezione del tutto per ogni bin, ma è quasi impossibile fare dei confronti. Per esempio, con un ritardo di -15 a 0 minuti, United Air Lines o JetBlue Airlines hanno una dimensione maggiore della barra? Non posso dirlo e nemmeno gli spettatori saranno in grado di farlo. Generalmente non sono un sostenitore delle barre impilate perché possono essere difficili da interpretare (anche se ci sono casi d’uso come quando si visualizzano le proporzioni). Entrambe le soluzioni che abbiamo provato usando gli istogrammi non hanno avuto successo, e quindi è il momento di passare al diagramma di densità.

Density Plots

Primo, cos’è un diagramma di densità? Un grafico di densità è una versione smussata e continua di un istogramma stimato dai dati. La forma più comune di stima è conosciuta come stima della densità del kernel. In questo metodo, una curva continua (il kernel) viene disegnata in ogni singolo punto dei dati e tutte queste curve vengono poi aggiunte insieme per fare una singola stima di densità liscia. Il kernel più spesso usato è una gaussiana (che produce una curva a campana gaussiana in ogni punto dei dati). Se, come me, trovate questa descrizione un po’ confusa, date un’occhiata al seguente grafico:

Kernel Density Estimation (Source)

Qui, ogni piccola linea nera verticale sull’asse delle x rappresenta un punto dati. I kernel individuali (Gaussiane in questo esempio) sono mostrati disegnati in linee rosse tratteggiate sopra ogni punto. La curva solida blu è creata sommando le singole gaussiane e forma il grafico di densità complessivo.

L’asse x è il valore della variabile proprio come in un istogramma, ma cosa rappresenta esattamente l’asse y? L’asse y in un grafico di densità è la funzione di densità di probabilità per la stima della densità del kernel. Tuttavia, dobbiamo fare attenzione a specificare che si tratta di una densità di probabilità e non di una probabilità. La differenza è che la densità di probabilità è la probabilità per unità sull’asse x. Per convertire in una probabilità effettiva, dobbiamo trovare l’area sotto la curva per un intervallo specifico sull’asse x. Un po’ confusamente, poiché questa è una densità di probabilità e non una probabilità, l’asse y può assumere valori maggiori di uno. L’unico requisito del grafico di densità è che l’area totale sotto la curva si integri a uno. In genere tendo a pensare all’asse y di un grafico di densità come un valore solo per i confronti relativi tra diverse categorie.

Piani di densità in Seaborn

Per fare i grafici di densità in seaborn, possiamo usare la funzione distplot o kdeplot. Continuerò ad usare la funzione distplot perché ci permette di fare più distribuzioni con una sola chiamata di funzione. Per esempio, possiamo fare un grafico di densità che mostra tutti i ritardi di arrivo sopra l’istogramma corrispondente:

# Density Plot and Histogram of all arrival delays
sns.distplot(flights, hist=True, kde=True,
bins=int(180/5), color = 'darkblue',
hist_kws={'edgecolor':'black'},
kde_kws={'linewidth': 4})

Piano di densità e istogramma usando seaborn

La curva mostra il grafico di densità che è essenzialmente una versione liscia dell’istogramma. L’asse y è in termini di densità, e l’istogramma è normalizzato per impostazione predefinita in modo da avere la stessa scala y del diagramma di densità.

Analogamente alla larghezza di banda di un istogramma, un diagramma di densità ha un parametro chiamato larghezza di banda che cambia i singoli kernel e influenza significativamente il risultato finale del grafico. La libreria di plottaggio sceglierà un valore ragionevole della larghezza di banda per noi (di default usando la stima ‘scott’), e a differenza della larghezza di banda di un istogramma, io di solito uso la larghezza di banda di default. Tuttavia, possiamo guardare di usare diverse larghezze di banda per vedere se c’è una scelta migliore. Nel grafico, ‘scott’ è l’opzione predefinita, che sembra la migliore.

Density Plot Showing different Bandwidths

Nota che una larghezza di banda più ampia risulta in una maggiore lisciatura della distribuzione. Vediamo anche che anche se abbiamo limitato i nostri dati da -60 a 120 minuti, il grafico di densità si estende oltre questi limiti. Questo è un potenziale problema con un grafico di densità: poiché calcola una distribuzione in ogni punto dei dati, può generare dati che cadono al di fuori dei limiti dei dati originali. Questo potrebbe significare che ci ritroviamo con valori impossibili sull’asse x che non sono mai stati presenti nei dati originali! Come nota, possiamo anche cambiare il kernel, che cambia la distribuzione disegnata in ogni punto dei dati e quindi la distribuzione complessiva. Tuttavia, per la maggior parte delle applicazioni, il kernel di default, Gaussiano, e la stima della larghezza di banda di default funzionano molto bene.

Soluzione #3 Density Plot

Ora che abbiamo capito come è fatto un density plot e cosa rappresenta, vediamo come può risolvere il nostro problema di visualizzare i ritardi di arrivo di più compagnie aeree. Per mostrare le distribuzioni sullo stesso grafico, possiamo iterare attraverso le compagnie aeree, ogni volta chiamando distplot con la stima della densità del kernel impostata su True e l’istogramma impostato su False. Il codice per disegnare il grafico di densità con più compagnie aeree è qui sotto:

Densità con più compagnie aeree

Finalmente, siamo arrivati ad una soluzione efficace! Con il diagramma di densità, possiamo facilmente fare confronti tra le compagnie aeree perché il diagramma è meno ingombrante. Ora che finalmente abbiamo il grafico che vogliamo, arriviamo alla conclusione che tutte queste compagnie aeree hanno distribuzioni di ritardo di arrivo quasi identiche! Tuttavia, ci sono altre compagnie aeree nel set di dati, e possiamo tracciarne uno che è un po’ diverso per illustrare un altro parametro opzionale per i grafici di densità, l’ombreggiatura del grafico.

Piani di densità ombreggiati

Riempire il grafico di densità può aiutarci a distinguere tra distribuzioni che si sovrappongono. Anche se questo non è sempre un buon approccio, può aiutare a sottolineare la differenza tra le distribuzioni. Per ombreggiare i diagrammi di densità, passiamo shade = True all’argomento kde_kws nella chiamata distplot.

sns.distplot(subset, hist = False, kde = True,
kde_kws = {'shade': True, 'linewidth': 3},
label = airline)

Shaded Density Plot

Se ombreggiare o meno il grafico è, come altre opzioni di tracciatura, una questione che dipende dal problema! Per questo grafico, penso che abbia senso perché l’ombreggiatura ci aiuta a distinguere i grafici nelle regioni in cui si sovrappongono. Ora, abbiamo finalmente qualche informazione utile: I voli Alaska Airlines tendono ad essere in anticipo più spesso di United Airlines. La prossima volta che hai l’opzione, sai quale compagnia aerea scegliere!

Rug Plots

Se vuoi mostrare ogni valore in una distribuzione e non solo la densità smussata, puoi aggiungere un rug plot. Questo mostra ogni singolo punto di dati sull’asse x, permettendoci di visualizzare tutti i valori reali. Il vantaggio di usare distplot di seaborn è che possiamo aggiungere il rug plot con una singola chiamata di parametro rug = True (con anche qualche formattazione).

Piano di densità con rug plot per Alaska Airlines

Con molti punti dati il rug plot può diventare sovraffollato, ma per alcune serie di dati, può essere utile visualizzare ogni punto dati. Il rug plot ci permette anche di vedere come il density plot “crea” dati dove non ce ne sono, perché crea una distribuzione kernel in ogni punto dei dati. Queste distribuzioni possono fuoriuscire dalla gamma dei dati originali e dare l’impressione che Alaska Airlines abbia ritardi che sono sia più brevi che più lunghi di quelli effettivamente registrati. Dobbiamo stare attenti a questo artefatto dei grafici di densità e farlo notare agli spettatori!

Conclusioni

Spero che questo post vi abbia dato una serie di opzioni per visualizzare una singola variabile da una o più categorie. Ci sono ancora più grafici univariati (di una singola variabile) che possiamo fare, come i grafici empirici di densità cumulativa e i grafici quantile-quantile, ma per ora ci limiteremo agli istogrammi e ai grafici di densità (e anche ai grafici a tappeto!). Non preoccupatevi se le opzioni sembrano schiaccianti: con la pratica, fare una buona scelta diventerà più facile, e potete sempre chiedere aiuto se necessario. Inoltre, spesso non c’è una scelta ottimale e la decisione “giusta” dipenderà dalle preferenze e dagli obiettivi della visualizzazione. La cosa buona è che non importa quale trama vogliate fare, ci sarà un modo per farlo in Python! Le visualizzazioni sono un mezzo efficace per comunicare i risultati, e conoscere tutte le opzioni disponibili ci permette di scegliere la figura giusta per i nostri dati.

Accetto feedback e critiche costruttive e posso essere raggiunto su Twitter @koehrsen_will.

admin

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.

lg