Visualizzare i Dati: Dare Senso ai Numeri con Matplotlib
I numeri, da soli, spesso non raccontano tutta la storia. Per afferrare davvero il significato nascosto nei tuoi dati, la visualizzazione è uno strumento indispensabile. Ci permette di esplorare pattern, individuare tendenze e comunicare informazioni complesse in modo immediato. Questo articolo ti guiderà attraverso Matplotlib, la libreria di plotting più utilizzata in Python, mostrandoti come trasformare i tuoi array NumPy in grafici chiari e parlanti che illumineranno i tuoi dati.
—
Introduzione a Matplotlib (Installazione e Importazione)
Matplotlib è una libreria completa per la creazione di grafici statici, animati e interattivi in Python. È strettamente integrata con NumPy e spesso viene usata insieme per visualizzare i risultati di calcoli numerici.
Per installare Matplotlib, apri il tuo terminale o prompt dei comandi e digita:
pip install matplotlib
Una volta installato, puoi importarlo nei tuoi script Python.
La convenzione standard è importare il modulo pyplot con l’alias plt:
import matplotlib.pyplot as plt
—
Creazione di Grafici Semplici (Linee, Scatter Plot)
Matplotlib rende semplice la creazione di grafici di base.
Vediamo come creare un grafico a linee e uno scatter plot usando dati generati con NumPy.
Grafico a Linee
Un grafico a linee è ideale per mostrare l’andamento di una variabile nel tempo o in relazione a un’altra variabile continua.
Esempio: Creiamo un grafico della funzione seno.
import numpy as np
import matplotlib.pyplot as plt
# Generiamo dati per l'asse x (valori da 0 a 2*pi)
x = np.linspace(0, 2 * np.pi, 100) # 100 punti equispaziati tra 0 e 2*pi
# Calcoliamo i valori corrispondenti per l'asse y (seno di x)
y = np.sin(x)
# Creiamo il grafico
plt.figure(figsize=(8, 6)) # Imposta le dimensioni della figura (larghezza, altezza in pollici)
plt.plot(x, y) # Crea il grafico a linee
# Aggiungiamo etichette e titolo per chiarezza
plt.xlabel("Angolo (radianti)")
plt.ylabel("Seno(Angolo)")
plt.title("Grafico della Funzione Seno")
plt.grid(True) # Aggiunge una griglia
# Mostriamo il grafico
plt.savefig("grafico_seno.png") # Salva il grafico come immagine
plt.show() # Mostra il grafico in una finestra separata

Spiegazione:
np.linspace(0, 2 * np.pi, 100)genera 100 punti tra [math]0[/math] e [math]2\pi[/math] (un ciclo completo del seno). Questi saranno i nostri valori sull’asse x.np.sin(x)calcola il seno di ogni valore inx, generando i valori sull’asse y.plt.figure(figsize=(8, 6))crea una nuova figura (la “tela” del grafico) con dimensioni specificate.plt.plot(x, y)è la funzione principale per disegnare il grafico a linee. Prende i valori x e y come input.plt.xlabel(),plt.ylabel(),plt.title()aggiungono etichette agli assi e un titolo al grafico, rendendolo più comprensibile.plt.grid(True)aggiunge una griglia di riferimento.plt.savefig("grafico_seno.png")salva il grafico come file immagine. Questo è utile in ambienti non interattivi o per includere i grafici in documenti.plt.show()è usato per visualizzare il grafico in una finestra separata quando si esegue lo script localmente. In un ambiente come questo, è preferibile salvare l’immagine.
L’uso di np.linspace(0, 2 * np.pi, 100) è fondamentale qui. Generare un numero sufficiente di punti equispaziati è cruciale per ottenere una curva liscia e rappresentativa della funzione seno. Se avessimo usato meno punti, il grafico apparirebbe “spigoloso” e non rifletterebbe la vera natura continua della funzione.
Questo tipo di grafico è estremamente utile in campi come la fisica, l’ingegneria e la finanza, dove si analizzano andamenti temporali o relazioni continue. Pensate alla variazione della temperatura durante il giorno, all’andamento del prezzo di un’azione nel tempo o alla propagazione di un’onda. Il grafico a linee eccelle nel mostrare l’evoluzione e le tendenze.
Scatter Plot
Uno scatter plot (grafico a dispersione) è utile per visualizzare la relazione tra due variabili numeriche, dove ogni punto rappresenta un’osservazione.
Esempio: Visualizziamo una relazione lineare con un po’ di rumore.
import numpy as np
import matplotlib.pyplot as plt
# Generiamo dati casuali
np.random.seed(42) # Per riproducibilità
x_scatter = np.random.rand(50) * 10 # 50 numeri casuali tra 0 e 10
y_scatter = 2 * x_scatter + 5 + np.random.randn(50) * 2 # Relazione lineare con rumore
# Creiamo lo scatter plot
plt.figure(figsize=(8, 6))
plt.scatter(x_scatter, y_scatter, color='red', alpha=0.7) # Crea lo scatter plot
# Aggiungiamo etichette e titolo
plt.xlabel("Variabile X")
plt.ylabel("Variabile Y")
plt.title("Scatter Plot di Dati Casuali")
plt.grid(True)
# Mostriamo il grafico
plt.savefig("scatter_plot.png")
plt.show()

Spiegazione:
np.random.rand(50) * 10genera 50 numeri casuali uniformemente distribuiti tra 0 e 10.np.random.randn(50) * 2genera 50 numeri casuali da una distribuzione normale standard (media 0, deviazione standard 1), che moltiplichiamo per 2 per aggiungere un “rumore” maggiore.plt.scatter(x_scatter, y_scatter, color='red', alpha=0.7)disegna i punti.colorimposta il colore dei punti,alphaimposta la trasparenza (utile quando ci sono molti punti sovrapposti).
L’introduzione di np.random.randn(50) * 2 simula il “rumore” o la variabilità intrinseca che si trova nei dati del mondo reale. Molto raramente le relazioni tra variabili sono perfette; c’è quasi sempre una certa dispersione. np.random.seed(42) è una pratica eccellente per la riproducibilità: assicura che, ogni volta che si esegue il codice, i numeri casuali generati siano gli stessi, rendendo i risultati dell’esempio consistenti.
Gli scatter plot sono lo strumento preferito per esplorare la relazione tra due variabili numeriche. Sono usati in analisi di mercato per vedere se c’è una correlazione tra spesa pubblicitaria e vendite, in biologia per capire la relazione tra altezza e peso, o in scienze sociali per studiare il legame tra anni di istruzione e reddito. Permettono di identificare pattern, cluster e potenziali outlier.
Visualizzazione di Array 2D (Heatmap)
Per visualizzare array 2D, specialmente matrici o dati tabellari, una heatmap è un’ottima scelta. Una heatmap rappresenta i valori numerici come colori, permettendo di identificare rapidamente pattern o valori anomali.
Esempio: Creiamo una heatmap di una matrice di correlazione (o dati casuali).
import numpy as np
import matplotlib.pyplot as plt
# Creiamo una matrice 5x5 di dati casuali
data_2d = np.random.rand(5, 5)
# Creiamo la heatmap
plt.figure(figsize=(7, 6))
plt.imshow(data_2d, cmap='viridis', interpolation='nearest')
plt.colorbar(label='Valore') # Aggiungiamo una barra dei colori
# Aggiungiamo etichette e titolo
plt.title("Heatmap di una Matrice Casuale")
# Mostriamo il grafico
plt.savefig("heatmap.png")
plt.show()

Spiegazione:
np.random.rand(5, 5)crea una matrice 5×5 di numeri casuali tra 0 e 1.plt.imshow(data_2d, cmap='viridis', interpolation='nearest')è la funzione chiave per creare la heatmap.cmap(colormap) definisce la scala di colori (es. ‘viridis’, ‘plasma’, ‘hot’, ‘gray’).interpolation='nearest'assicura che i pixel siano visualizzati come blocchi distinti, senza sfumature.plt.colorbar(label='Valore')aggiunge una barra dei colori che indica la corrispondenza tra colori e valori numerici.
cmap='viridis' e interpolation='nearest' sono scelte importanti. Il colormap ‘viridis’ è perceptually uniform, il che significa che la percezione del cambio di colore è lineare rispetto al cambio di valore, rendendolo ideale per la visualizzazione di dati. interpolation='nearest' evita sfumature tra i pixel, che è utile quando ogni cella della matrice rappresenta un valore discreto, come spesso accade nelle matrici di correlazione o nei dati tabellari.
Le heatmap sono eccezionali per visualizzare matrici di dati 2D, come matrici di correlazione, matrici di confusione nell’apprendimento automatico, o dati tabellari complessi. Permettono di identificare a colpo d’occhio aree di alta o bassa intensità, evidenziando pattern o anomalie che sarebbero difficili da cogliere solo con i numeri. Immagina di visualizzare i flussi di traffico tra diverse città o i punteggi di un questionario multidimensionale.
Esempi di Visualizzazione di Dati Generati con NumPy
Combinando le capacità di generazione dati di NumPy con le funzionalità di plotting di Matplotlib, possiamo creare visualizzazioni significative per vari scenari.
Esempio: Distribuzione di dati casuali (istogramma).
Un istogramma mostra la distribuzione di una singola variabile numerica, dividendo i dati in “bin” e contando quanti valori cadono in ogni bin.
import numpy as np
import matplotlib.pyplot as plt
# Generiamo 1000 numeri casuali da una distribuzione normale (gaussiana)
dati_normali = np.random.randn(1000)
# Creiamo l'istogramma
plt.figure(figsize=(8, 6))
plt.hist(dati_normali, bins=30, edgecolor='black', alpha=0.7)
# Aggiungiamo etichette e titolo
plt.xlabel("Valore")
plt.ylabel("Frequenza")
plt.title("Istogramma di Dati con Distribuzione Normale")
plt.grid(axis='y', alpha=0.75)
# Mostriamo il grafico
plt.savefig("istogramma_normale.png")
plt.show()

Spiegazione:
np.random.randn(1000)genera 1000 campioni da una distribuzione normale standard.plt.hist(dati_normali, bins=30, edgecolor='black', alpha=0.7)crea l’istogramma.binsspecifica il numero di intervalli in cui dividere i dati.edgecolorealphamigliorano l’estetica.
bins=30 è un parametro chiave. La scelta del numero di bin influisce significativamente sull’aspetto dell’istogramma e su come viene percepita la distribuzione. Troppi pochi bin possono nascondere dettagli importanti, mentre troppi possono rendere il grafico troppo “rumoroso”. L’uso di edgecolor='black' migliora la leggibilità distinguendo chiaramente un bin dall’altro.
In un istogramma,
binsrappresenta il numero di intervalli (o “barre”) in cui vengono raggruppati i dati sull’asse orizzontale (l’asse dei valori).Immagina di avere un insieme di dati, ad esempio le altezze di 100 persone. Se vuoi creare un istogramma per visualizzare come si distribuiscono queste altezze, il parametro
binsti dice quante “categorie” di altezza vuoi creare.Ecco cosa significa in pratica:
- Suddivisione dell’Intervallo: Matplotlib (o qualsiasi strumento per istogrammi) prende l’intero intervallo di valori presenti nei tuoi dati (dal minimo al massimo) e lo divide in un numero specificato di sotto-intervalli di uguale larghezza. Ogni sotto-intervallo è un “bin”.
- Conteggio della Frequenza: Per ogni bin, l’istogramma conta quanti punti dati cadono all’interno di quell’intervallo.
- Rappresentazione Grafica: Ogni bin viene poi rappresentato da una barra la cui altezza indica la frequenza (o il conteggio) dei dati che rientrano in quell’intervallo.
Gli istogrammi sono lo strumento principale per comprendere la distribuzione di una singola variabile numerica. Sono fondamentali in statistica e analisi dati per verificare se i dati seguono una distribuzione nota (come la normale), identificare asimmetrie, bimodalità o valori anomali. Sono ampiamente usati per analizzare l’età di un gruppo di persone, i tempi di risposta di un server o la frequenza dei punteggi in un test.
Personalizzazione Avanzata dei Grafici
Matplotlib offre un controllo granulare su quasi ogni aspetto dei tuoi grafici. Puoi modificare tipi di linea, marcatori, colori, aggiungere legende per identificare diverse serie di dati e persino annotazioni per evidenziare punti specifici.
Esempio: Grafico a linee con più serie e legenda.
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 2 * np.pi, 100)
y1 = np.sin(x)
y2 = np.cos(x)
y3 = np.sin(x) * np.cos(x) # Una terza funzione per esempio
plt.figure(figsize=(10, 6))
# Serie 1: linea blu, spessa, con etichetta
plt.plot(x, y1, color='blue', linestyle='-', linewidth=2, label='Seno(x)')
# Serie 2: linea rossa, tratteggiata, con etichetta
plt.plot(x, y2, color='red', linestyle='--', linewidth=1.5, label='Coseno(x)')
# Serie 3: linea verde, con marcatori a cerchio e etichetta
plt.plot(x, y3, color='green', linestyle=':', marker='o', markersize=4, label='Seno(x)*Coseno(x)')
plt.xlabel("Angolo (radianti)")
plt.ylabel("Valore")
plt.title("Funzioni Trigonometriche a Confronto")
plt.grid(True)
plt.legend() # Mostra la legenda basandosi sulle etichette delle serie
plt.savefig("grafico_personalizzato.png")
# plt.show()
Spiegazione:
- Abbiamo aggiunto più chiamate a
plt.plot(), ciascuna per una diversa funzione. - Parametri come
color,linestyle(es. ‘-‘, ‘–‘, ‘:’, ‘-.’),linewidthemarker(es. ‘o’, ‘x’, ‘^’) ti danno il controllo sull’aspetto di ogni linea. - Il parametro
labelall’interno diplt.plot()è fondamentale, perchéplt.legend()utilizza queste etichette per creare la legenda, rendendo chiaro quale linea rappresenta quale dato.
Sottografici (Subplots): Organizzare più grafici
Spesso è utile visualizzare più grafici affiancati all’interno della stessa figura per confrontare diverse visualizzazioni o diverse serie di dati. Matplotlib facilita questo compito con plt.subplots().
import numpy as np
import matplotlib.pyplot as plt
# Dati per i sottografici
x = np.linspace(0, 10, 100)
y_sin = np.sin(x)
y_cos = np.cos(x)
y_exp = np.exp(-x/2) * np.sin(x*5) # Esempio di funzione ammortizzata
y_linear = 2 * x + 1
# Crea una figura con 2 righe e 2 colonne di sottografici
fig, axs = plt.subplots(2, 2, figsize=(12, 10)) # fig è la figura, axs è un array di assi
# Grafico 1: Seno
axs[0, 0].plot(x, y_sin, color='blue')
axs[0, 0].set_title("Funzione Seno")
axs[0, 0].set_xlabel("X")
axs[0, 0].set_ylabel("Y")
axs[0, 0].grid(True)
# Grafico 2: Coseno
axs[0, 1].plot(x, y_cos, color='red')
axs[0, 1].set_title("Funzione Coseno")
axs[0, 1].set_xlabel("X")
axs[0, 1].set_ylabel("Y")
axs[0, 1].grid(True)
# Grafico 3: Funzione ammortizzata
axs[1, 0].plot(x, y_exp, color='green')
axs[1, 0].set_title("Funzione Esponenziale Ammortizzata")
axs[1, 0].set_xlabel("X")
axs[1, 0].set_ylabel("Y")
axs[1, 0].grid(True)
# Grafico 4: Relazione Lineare
axs[1, 1].scatter(x, y_linear + np.random.randn(len(x))*2, color='purple', alpha=0.6)
axs[1, 1].set_title("Dati Lineari con Rumore")
axs[1, 1].set_xlabel("X")
axs[1, 1].set_ylabel("Y")
axs[1, 1].grid(True)
# Regola la spaziatura tra i sottografici per evitare sovrapposizioni
plt.tight_layout()
plt.savefig("sottografici.png")
# plt.show()
Spiegazione:
fig, axs = plt.subplots(2, 2, figsize=(12, 10))crea una figura (fig) e un array di oggettiAxes(axs). In questo caso,axssarà una matrice 2×2.- Ogni elemento di
axs(es.axs[0, 0],axs[0, 1], ecc.) rappresenta un singolo sottografo. Per tracciare su un sottografo specifico e impostare i suoi titoli/etichette, si usano i metodi dell’oggettoAxes(comeplot(),set_title(),set_xlabel(),set_ylabel(),grid()) invece delle funzioni globaliplt.. plt.tight_layout()regola automaticamente i parametri del sottografo per dare un layout stretto e prevenire la sovrapposizione degli elementi.





