Creare dashboard di analisi con subplot e GridSpec in Matplotlib

by theArchitect
SHARE
Creare dashboard di analisi con subplot e GridSpec in Matplotlib
© Guida-HTML5.it

Introduzione

Quando un dataset contiene molte informazioni, un singolo grafico può non essere sufficiente. In questi casi è utile costruire una piccola dashboard composta da più visualizzazioni coordinate. Matplotlib permette di organizzare diversi grafici nella stessa figura usando i subplot e il layout avanzato GridSpec.

Questo approccio è particolarmente utile per analizzare, ad esempio, le prestazioni di un negozio online. Possiamo mostrare contemporaneamente:

  • la distribuzione degli ordini per categoria;
  • il confronto tra ricavi e numero di prodotti venduti;
  • la relazione tra sconto applicato e valore dell´ordine;
  • la distribuzione dei tempi di consegna.

La visualizzazione multipannello consente di confrontare prospettive diverse senza aprire numerose finestre separate. Un buon layout deve però essere leggibile: ogni pannello deve avere un titolo chiaro, assi comprensibili e una dimensione adeguata.

Codice completo

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec

# Generatore casuale con risultato riproducibile
rng = np.random.default_rng(42)

# Dati simulati relativi a 180 ordini
categorie = np.array(["Elettronica", "Casa", "Libri", "Sport"])
categoria_ordini = rng.choice(categorie, size=180)

prezzi = rng.uniform(15, 250, size=180)
quantita = rng.integers(1, 5, size=180)
sconti = rng.uniform(0, 35, size=180)

# Il ricavo dipende dal prezzo, dalla quantità e dallo sconto
ricavi = prezzi * quantita * (1 - sconti / 100)

# Tempi di consegna simulati in giorni
tempi_consegna = np.maximum(
    rng.normal(loc=4.5, scale=1.7, size=180),
    1
)

# Creiamo una figura con una griglia di 2 righe e 2 colonne
fig = plt.figure(figsize=(13, 8), constrained_layout=True)
griglia = GridSpec(2, 2, figure=fig)

# Pannello 1: ricavi medi per categoria
ax1 = fig.add_subplot(griglia[0, 0])

ricavi_medi = [
    ricavi[categoria_ordini == categoria].mean()
    for categoria in categorie
]

colori = ["#4575b4", "#74add1", "#fdae61", "#d73027"]

ax1.bar(categorie, ricavi_medi, color=colori)
ax1.set_title("Ricavo medio per categoria")
ax1.set_ylabel("Ricavo medio (€)")
ax1.tick_params(axis="x", rotation=20)
ax1.grid(axis="y", alpha=0.3)

# Pannello 2: relazione tra sconto e ricavo
ax2 = fig.add_subplot(griglia[0, 1])

punti = ax2.scatter(
    sconti,
    ricavi,
    c=quantita,
    cmap="viridis",
    alpha=0.7,
    edgecolors="white",
    linewidths=0.5
)

ax2.set_title("Sconto e valore dell´ordine")
ax2.set_xlabel("Sconto (%)")
ax2.set_ylabel("Ricavo (€)")
ax2.grid(alpha=0.25)

# La barra dei colori spiega il significato del colore dei punti
barra_colori = fig.colorbar(punti, ax=ax2)
barra_colori.set_label("Quantità acquistata")

# Pannello 3: numero di ordini per categoria
ax3 = fig.add_subplot(griglia[1, 0])

conteggi = [
    np.sum(categoria_ordini == categoria)
    for categoria in categorie
]

ax3.barh(categorie, conteggi, color="#66c2a5")
ax3.set_title("Numero di ordini")
ax3.set_xlabel("Ordini")
ax3.grid(axis="x", alpha=0.3)

# Scriviamo il valore direttamente accanto a ogni barra
for indice, valore in enumerate(conteggi):
    ax3.text(valore + 1, indice, str(valore), va="center")

# Pannello 4: distribuzione dei tempi di consegna
ax4 = fig.add_subplot(griglia[1, 1])

ax4.boxplot(
    tempi_consegna,
    vert=False,
    patch_artist=True,
    boxprops={"facecolor": "#fdae61"},
    medianprops={"color": "black", "linewidth": 2}
)

ax4.set_title("Distribuzione dei tempi di consegna")
ax4.set_xlabel("Giorni")
ax4.set_yticks([])
ax4.grid(axis="x", alpha=0.3)

# Titolo generale della dashboard
fig.suptitle(
    "Dashboard riepilogativa degli ordini",
    fontsize=18,
    fontweight="bold"
)

# Salvataggio ad alta risoluzione
fig.savefig(
    "dashboard_ordini.png",
    dpi=150,
    bbox_inches="tight"
)

plt.show()

Spiegazione

Costruire la griglia

GridSpec permette di descrivere la disposizione dei pannelli come una griglia. Nell´esempio, GridSpec(2, 2) crea due righe e due colonne. Ogni grafico viene inserito in una posizione specifica tramite espressioni come griglia[0, 0] o griglia[1, 1].

La funzione fig.add_subplot() collega un asse alla figura principale. Ogni oggetto restituito, come ax1 o ax2, rappresenta un pannello indipendente sul quale è possibile disegnare e impostare titoli, etichette e griglie.

Perché usare GridSpec invece di una semplice griglia

Per layout regolari si può usare anche plt.subplots(2, 2). GridSpec è però più flessibile: consente di far occupare a un pannello più righe o più colonne. Per esempio, un asse può essere creato con fig.add_subplot(griglia[:, 0]), occupando tutta la prima colonna.

Questa flessibilità è utile quando un grafico principale deve essere più grande dei grafici di supporto. Una dashboard reale potrebbe avere un grafico di sintesi largo quanto l´intera finestra e due grafici più piccoli sotto di esso.

Usare colori e annotazioni

Nel secondo pannello, il colore dei punti rappresenta la quantità acquistata. La funzione fig.colorbar() aggiunge una legenda cromatica, indispensabile quando il colore contiene informazione.

Nel grafico a barre orizzontali i valori vengono scritti accanto alle barre con ax3.text(). Questa tecnica evita che il lettore debba stimare il valore osservando soltanto la scala dell´asse.

Gestire lo spazio

L´argomento constrained_layout=True aiuta Matplotlib a evitare sovrapposizioni tra titoli, etichette e barra dei colori. È una soluzione moderna e spesso preferibile a chiamare manualmente plt.tight_layout().

Best practice

  • Definisci una domanda per ogni pannello: ogni grafico dovrebbe rispondere a un quesito concreto, non essere inserito soltanto per riempire lo spazio.
  • Usa titoli descrittivi: “Ricavo medio per categoria” è più utile di un titolo generico come “Grafico 1”.
  • Mantieni una gerarchia visiva: il titolo generale deve essere più evidente dei titoli dei singoli pannelli.
  • Evita troppe palette diverse: colori coerenti rendono la dashboard più professionale e leggibile.
  • Non duplicare le legende: se una stessa codifica cromatica è condivisa, valuta l´uso di una sola legenda comune.
  • Controlla le dimensioni: una figura troppo piccola rende il testo illeggibile, soprattutto quando contiene quattro o più pannelli.
  • Salva con una risoluzione adeguata: per report e presentazioni, dpi=150 o dpi=300 produce immagini più nitide.
  • Considera l´accessibilità: non affidarti soltanto al colore; aggiungi etichette, forme o annotazioni per comunicare i dati.

Riepilogo

Una dashboard composta da più subplot permette di osservare lo stesso fenomeno da punti di vista differenti. Con GridSpec possiamo controllare con precisione la disposizione degli assi e creare layout più flessibili rispetto a una semplice griglia uniforme.

Le idee principali sono:

  • creare una figura principale con plt.figure();
  • definire la struttura con GridSpec;
  • aggiungere ogni pannello tramite fig.add_subplot();
  • personalizzare ogni asse indipendentemente;
  • usare constrained_layout e savefig() per ottenere un risultato ordinato e riutilizzabile.

Approfondisci con risorse ufficiali

SHARE