W3docs

Grafici a Dispersione con Matplotlib in Python — Guida Completa

Impara a creare e personalizzare grafici a dispersione in Python con Matplotlib. Tratta colori, dimensioni, alpha, colorbar, gruppi multipli e annotazioni.

La funzione scatter() di Matplotlib ti consente di visualizzare la relazione tra due variabili numeriche posizionando un marcatore in ogni punto dati (x, y). A differenza di un grafico a linee, i grafici a dispersione non assumono nulla riguardo all'ordine o alla continuità — ogni punto è indipendente. Questo li rende la scelta ideale per esplorare correlazioni, individuare cluster e rilevare valori anomali.

Questo capitolo tratta tutto, dal primo grafico a dispersione alle tecniche professionali: codifica per punto di colore e dimensione, trasparenza, colorbar, grafici multi-gruppo, annotazioni dei punti e salvataggio di file pronti per la pubblicazione.

Prima di iniziare, assicurati che Matplotlib sia installato:

pip install matplotlib

Se sei nuovo a Matplotlib, leggi prima i capitoli Introduzione a Matplotlib e Guida Introduttiva.

Quando Usare un Grafico a Dispersione

Usa un grafico a dispersione quando:

  • Vuoi esplorare la correlazione tra due variabili numeriche (altezza vs. peso, ore di studio vs. punteggio all'esame).
  • Hai bisogno di rilevare cluster — gruppi di punti che si raggruppano naturalmente.
  • Vuoi identificare valori anomali — punti lontani dalla distribuzione principale.
  • Stai codificando una terza variabile tramite la dimensione o il colore del marcatore (un "bubble chart" è un grafico a dispersione in cui la dimensione = una terza variabile).

Evita i grafici a dispersione quando un asse rappresenta categorie non ordinate — un grafico a barre è più chiaro in quel caso. Per tendenze su una variabile continua ordinata, un grafico a linee è più appropriato.

Creare un Grafico a Dispersione di Base

Passa due sequenze di uguale lunghezza — valori x e valori y — a plt.scatter():

import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
y = [2, 4, 5, 4, 7, 8, 6, 9, 10, 12]

plt.scatter(x, y)

plt.title('Basic Scatter Plot')
plt.xlabel('X Values')
plt.ylabel('Y Values')

plt.tight_layout()
plt.show()

plt.tight_layout() impedisce che le etichette vengano troncate — usalo prima di ogni chiamata a show() o savefig().

Personalizzare la Dimensione dei Marcatori

Il parametro s controlla la dimensione dei marcatori in punti quadrati (il valore predefinito è 20). Aumentalo per rendere i punti più visibili, specialmente nelle presentazioni:

import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5, 6, 7, 8]
y = [3, 1, 4, 1, 5, 9, 2, 6]

plt.scatter(x, y, s=120)

plt.title('Larger Markers')
plt.xlabel('X')
plt.ylabel('Y')
plt.tight_layout()
plt.show()

Puoi anche passare una lista o array a s in modo che ogni punto abbia la propria dimensione — è così che si codifica una terza variabile numerica come dimensione delle bolle:

import matplotlib.pyplot as plt

x      = [1, 2, 3, 4, 5]
y      = [5, 3, 6, 2, 7]
sizes  = [100, 300, 50, 400, 200]   # third variable encoded as bubble area

plt.scatter(x, y, s=sizes)

plt.title('Bubble Chart — size encodes a third variable')
plt.xlabel('X')
plt.ylabel('Y')
plt.tight_layout()
plt.show()

Personalizzare il Colore dei Marcatori

Un Singolo Colore per Tutti i Punti

Passa qualsiasi nome di colore, stringa esadecimale o tupla RGB a c (o color):

import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5]
y = [2, 4, 1, 5, 3]

plt.scatter(x, y, s=100, c='steelblue')

plt.title('Single Color')
plt.xlabel('X')
plt.ylabel('Y')
plt.tight_layout()
plt.show()

Colore per Punto da una Variabile Numerica

Passare un array a c mappa ogni valore a un colore tramite la mappa cromatica specificata in cmap. Aggiungi plt.colorbar() per mostrare cosa rappresentano i colori:

import matplotlib.pyplot as plt
import numpy as np

rng = np.random.default_rng(seed=42)
x      = rng.random(50)
y      = rng.random(50)
values = rng.random(50)          # third variable, e.g. intensity or temperature

scatter = plt.scatter(x, y, s=80, c=values, cmap='viridis')
plt.colorbar(scatter, label='Intensity')

plt.title('Color-Mapped Scatter Plot')
plt.xlabel('X')
plt.ylabel('Y')
plt.tight_layout()
plt.show()

'viridis' è una mappa cromatica percettivamente uniforme, leggibile in scala di grigi e accessibile ai lettori daltonici. Altre buone scelte sono 'plasma', 'cividis' e 'coolwarm'.

Controllo della Trasparenza con alpha

Quando molti punti si sovrappongono, formano una massa opaca che nasconde la vera densità. Imposta alpha (0 = completamente trasparente, 1 = completamente opaco) per rivelare la struttura sovrapposta:

import matplotlib.pyplot as plt
import numpy as np

rng = np.random.default_rng(seed=0)
x = rng.normal(loc=0, scale=1, size=300)
y = rng.normal(loc=0, scale=1, size=300)

plt.scatter(x, y, s=40, alpha=0.4)

plt.title('Transparent Markers Reveal Density (alpha=0.4)')
plt.xlabel('X')
plt.ylabel('Y')
plt.tight_layout()
plt.show()

Un buon punto di partenza è alpha=0.4 fino a 0.6. Regola in base al numero di punti.

Stilizzare i Bordi dei Marcatori

Usa edgecolors per aggiungere un bordo intorno a ogni marcatore e linewidths per controllare lo spessore del bordo. Questo aiuta i punti a risaltare su uno sfondo colorato:

import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5, 6]
y = [3, 1, 4, 1, 5, 9]

plt.scatter(x, y, s=150, c='gold', edgecolors='black', linewidths=1.5)

plt.title('Markers with Edges')
plt.xlabel('X')
plt.ylabel('Y')
plt.tight_layout()
plt.show()

Passa edgecolors='none' per rimuovere completamente i bordi (questo è il valore predefinito per la maggior parte delle mappe cromatiche).

Tracciare Gruppi Multipli

Per confrontare i gruppi, chiama plt.scatter() una volta per gruppo e assegna un'etichetta. Matplotlib assegna automaticamente un colore diverso a ogni chiamata:

import matplotlib.pyplot as plt
import numpy as np

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

# Group A — centered around (2, 3)
ax_x = rng.normal(loc=2, scale=0.5, size=30)
ax_y = rng.normal(loc=3, scale=0.5, size=30)

# Group B — centered around (5, 6)
bx_x = rng.normal(loc=5, scale=0.5, size=30)
bx_y = rng.normal(loc=6, scale=0.5, size=30)

# Group C — centered around (8, 2)
cx_x = rng.normal(loc=8, scale=0.5, size=30)
cx_y = rng.normal(loc=2, scale=0.5, size=30)

plt.scatter(ax_x, ax_y, s=60, label='Group A')
plt.scatter(bx_x, bx_y, s=60, label='Group B')
plt.scatter(cx_x, cx_y, s=60, label='Group C')

plt.legend()
plt.title('Multi-Group Scatter Plot')
plt.xlabel('X')
plt.ylabel('Y')
plt.tight_layout()
plt.show()

Ogni chiamata a scatter() sceglie automaticamente il colore successivo nel ciclo di colori predefinito. Passa c='red' (o qualsiasi colore) per sovrascrivere.

Annotare i Singoli Punti

Usa plt.annotate() per etichettare punti specifici — utile per evidenziare valori anomali o osservazioni chiave:

import matplotlib.pyplot as plt

cities = ['London', 'Berlin', 'Madrid', 'Rome', 'Paris']
population = [9.0, 3.7, 3.3, 2.8, 2.1]   # millions
area       = [1572, 892, 604, 1285, 105]   # km²

plt.scatter(area, population, s=100, c='steelblue', edgecolors='black', linewidths=0.8)

for i, city in enumerate(cities):
    plt.annotate(
        city,
        xy=(area[i], population[i]),
        xytext=(8, 4),                      # offset in points
        textcoords='offset points',
        fontsize=9,
    )

plt.title('European City Population vs. Area')
plt.xlabel('Area (km²)')
plt.ylabel('Population (millions)')
plt.tight_layout()
plt.show()

Il pattern xytext + textcoords='offset points' sposta leggermente l'etichetta in modo che non si sovrapponga direttamente al marcatore.

Uso degli Assi Logaritmici

Quando i dati si estendono su diversi ordini di grandezza, gli assi lineari comprimono la maggior parte dei punti in un angolo. Passa a una scala logaritmica con plt.xscale('log') o plt.yscale('log'):

import matplotlib.pyplot as plt
import numpy as np

rng = np.random.default_rng(seed=1)
x = np.logspace(1, 5, 60)            # 10¹ to 10⁵
y = x * rng.uniform(0.5, 2.0, 60)   # roughly proportional, with noise

plt.scatter(x, y, s=40, alpha=0.7)
plt.xscale('log')
plt.yscale('log')

plt.title('Log-Scale Scatter Plot')
plt.xlabel('X (log scale)')
plt.ylabel('Y (log scale)')
plt.tight_layout()
plt.show()

Entrambi gli assi coprono ora intervalli uniformi di potenze di dieci, distribuendo i dati in modo uniforme sull'area del grafico.

Aggiungere una Linea di Regressione

Un grafico a dispersione mostra i singoli punti; aggiungere una linea di miglior adattamento mostra la tendenza generale. Calcola pendenza e intercetta con np.polyfit():

import matplotlib.pyplot as plt
import numpy as np

rng = np.random.default_rng(seed=3)
x = np.linspace(0, 10, 40)
y = 2.5 * x + rng.normal(scale=3, size=40)   # linear trend + noise

# Fit a degree-1 polynomial (straight line)
slope, intercept = np.polyfit(x, y, 1)
trend_line = slope * x + intercept

plt.scatter(x, y, s=50, label='Data points', alpha=0.7)
plt.plot(x, trend_line, color='red', linewidth=2, label=f'Trend (slope={slope:.2f})')

plt.legend()
plt.title('Scatter Plot with Regression Line')
plt.xlabel('X')
plt.ylabel('Y')
plt.tight_layout()
plt.show()

np.polyfit(x, y, 1) restituisce [slope, intercept] per la retta di miglior adattamento che passa per i punti.

Salvare un Grafico a Dispersione su File

Usa plt.savefig() invece di plt.show() per scrivere il grafico su disco. Chiamalo prima di plt.show() — dopo show() la figura viene cancellata:

import matplotlib.pyplot as plt
import numpy as np

rng = np.random.default_rng(seed=9)
x = rng.random(60)
y = rng.random(60)

plt.scatter(x, y, s=60, alpha=0.6, c='teal', edgecolors='white', linewidths=0.5)
plt.title('Saved Scatter Plot')
plt.xlabel('X')
plt.ylabel('Y')
plt.tight_layout()

plt.savefig('scatter.png', dpi=150)   # PNG at 150 DPI
plt.savefig('scatter.pdf')             # vector PDF — best for publication
plt.show()

Opzioni di formato comuni: 'png' (raster, web), 'pdf' (vettoriale, pubblicazione), 'svg' (vettoriale, web). Aumenta dpi a 300 per raster di qualità stampa.

scatter() vs plot() — Quale Usare?

Entrambe le funzioni possono tracciare grafici con soli marcatori, ma servono a scopi diversi:

Funzionalitàplt.scatter()plt.plot()
Dimensione per punto (s)Sì — passa un arrayNo
Colore per punto (c)Sì — passa un arrayNo (un colore per chiamata)
Supporto mappa cromaticaSì (cmap)Limitato
Prestazioni con grandi datasetPiù lentoPiù veloce
Linea di collegamentoNo

Usa scatter() quando hai bisogno di stili per punto (il colore o la dimensione varia in base ai dati). Usa plot(marker='o', linestyle='None') per grafici a marcatori semplici su grandi dataset dove la velocità è importante. Consulta il capitolo Matplotlib Markers per ulteriori informazioni sugli stili dei marcatori.

Esempio Completo

Il seguente script autonomo combina le tecniche più utili — mappatura dei colori, codifica della dimensione, trasparenza, una colorbar e una legenda:

import matplotlib.pyplot as plt
import numpy as np

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

n = 80
x      = rng.standard_normal(n)
y      = 0.8 * x + rng.standard_normal(n) * 0.6   # correlated
sizes  = rng.uniform(30, 200, n)                   # bubble area
values = rng.random(n)                             # third variable for color

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

sc = ax.scatter(
    x, y,
    s=sizes,
    c=values,
    cmap='plasma',
    alpha=0.75,
    edgecolors='white',
    linewidths=0.5,
)

plt.colorbar(sc, ax=ax, label='Intensity')

ax.set_title('Comprehensive Scatter Plot Example', fontsize=13)
ax.set_xlabel('X Variable')
ax.set_ylabel('Y Variable (correlated)')
fig.tight_layout()
plt.savefig('scatter_complete.png', dpi=150)
plt.show()

Punti chiave:

  • fig, ax = plt.subplots() fornisce oggetti figura e assi espliciti — l'approccio consigliato per qualsiasi cosa oltre a un prototipo rapido.
  • ax.scatter() su un oggetto Axes si comporta in modo identico a plt.scatter().
  • plt.colorbar(sc, ax=ax, label='...') collega la colorbar agli assi specifici.

Best Practice

  • Mostra la scala. Se usi c con una mappa cromatica, aggiungi sempre una colorbar in modo che i lettori sappiano cosa rappresentano i colori.
  • Evita il sovraffollamento. Per più di circa 500 punti, imposta alpha < 1 o passa a un istogramma 2D (plt.hist2d()) o a un grafico hexbin (plt.hexbin()).
  • Scegli mappe cromatiche accessibili. 'viridis', 'plasma' e 'cividis' sono percettivamente uniformi e adatte ai daltonici. Evita 'jet' e 'rainbow'.
  • Etichetta gli assi con le unità. plt.xlabel('Altezza (cm)') è più informativo di plt.xlabel('Altezza').
  • Aggiungi un titolo che indichi il risultato. "Altezza vs. Peso — correlazione positiva" è più utile di "Grafico a Dispersione".

Capitoli Correlati

Was this page helpful?