Open In Colab

7. Introduzione a Matplotlib#

Matplotlib è la libreria Python più comune per la creazione di grafici. Possiamo caricare il modulo pyplot utilizzando la seguente istruzione. Utilizzando la parola chiave as, possiamo assegnare un alias al modulo importato, che è un nome più breve per fare riferimento alle sue funzioni e metodi. Ad esempio, nell’esempio seguente potremo accedere alle funzioni e ai metodi del modulo matplotlib.pyplot utilizzando semplicemente l’alias plt.

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
import arviz as az
%matplotlib inline

# Initialize random number generator
RANDOM_SEED = 8927
rng = np.random.default_rng(RANDOM_SEED)

plt.style.use("bmh")
plt.rcParams["figure.figsize"] = [10, 6]
plt.rcParams["figure.dpi"] = 100
plt.rcParams["figure.facecolor"] = "white"

sns.set_theme(palette="colorblind")

%load_ext autoreload
%autoreload 2
%config InlineBackend.figure_format = "svg"

La linea di codice %matplotlib inline fa riferimento a una caratteristica dei nootbook Juupyter: tutte le linee che iniziano con il carattere % vengono chiamate line magic e permettono di effettuare operazioni supplementari. In questo caso si tratta di una matplotlib magic che specifica che i grafici prodotti da matplotlib devono essere visualizzati direttamente nel notebook (senza questa operazione i grafici non verrebbero mostrati automaticamente). È sufficiente specificare la matplotlib magic una sola volta, all’inizio del notebook oppure prima di produrre il primo grafico da visualizzare. Da quel punto in avanti tutti i grafici verranno automaticamente mostrati nel notebook.

7.1. Il modulo pyplot#

L’istruzione fig, ax = plt.subplots() viene utilizzata per creare una figura e un set di assi (ovvero, subplot) all’interno di quella figura. Con l’istruzione seguente generiamo semplicemente una figura vuota.

fig, ax = plt.subplots()
_images/55dc9e5e7d85cf96a06eab93e5ea3197b89da9b8dfa5a14aab5e5002f7ce3159.svg

Supponiamo di avere i seguenti dati.

# this is dataset 1 from
# https://en.wikipedia.org/wiki/Anscombe%27s_quartet
data_x = [10.0, 8.0, 13.0, 9.0, 11.0, 14.0, 6.0, 4.0, 12.0, 7.0, 5.0]
data_y = [8.04, 6.95, 7.58, 8.81, 8.33, 9.96, 7.24, 4.26, 10.84, 4.82, 5.68]

Possiamo generare un diagramma a dispersione con il scatter. Le etichette per gli assi \(x\) e \(y\) possono essere specificate con i metodi set_xlabel, set_xlabel. Il titolo viene specificato mediante il metodo set_title.

fig, ax = plt.subplots()

ax.scatter(x=data_x, y=data_y)
ax.set_xlabel("we should label the x axis")
ax.set_ylabel("we should label the y axis")
ax.set_title("some title")
Text(0.5, 1.0, 'some title')
_images/2dbac516d3b8665fe2d0d0c4ed153b18e86fadca81f2a82fe1ed9b27b1e7e4af.svg

7.1.1. Funzione plot#

Le quantità da plottare sono ndarrays, ma anche una lista viene trasformata direttamente in un array quando viene passata come argomento del plot. Esempio:

fig, ax = plt.subplots()
_ = ax.plot([1, 2, 3, 4])
_images/762e01425ed59a78ae2e61d8bb0764aaf9e759ff214cfbc807f61795886bd0df.svg

Una lista unica viene interpretata come la funzione da plottare lungo y, ma se ne passiamo due la prima viene interpretata come asse x. Infine, una stringa come terzo parametro viene interpretata come un descrittore per il colore della linea, lo stile, ecc.

Esempio: disegno di dati contenuti in due liste con linea continua (parametro ‘-’) e pallini rossi (parametro ‘or’)…

x = [1, 2, 3, 4]
y = [1, 4, 9, 16]

fig, ax = plt.subplots()
_ = ax.plot(x, y, "or-")
_images/dc2daf3c4374daf1d37e9b199f64c94f95cac142c3ac634e5b43c4e1dde2cea8.svg

Oppure si possono definire due o più ndarrays, da passare al plot. Nell’esempio seguente vengono definite due funzioni da rappresentare in un unico grafico (si noti il colore differente prima del -):

x = np.linspace(0.0, 2.0 * np.pi, 101)
y = np.sin(x)
z = np.cos(x)

fig, ax = plt.subplots()
ax.plot(x, y, "b-")
_ = ax.plot(x, z, "r-")
_images/db7206f15fa01acbf45b6707a1248ec9b7b74b24050a19c00010ffa5fd5c17f7.svg

Possiamo anche scrivere, in maniera più succinta, quanto segue

fig, ax = plt.subplots()
_ = ax.plot(x, y, "g-", x, z, "b-")
_images/25fda72dcbb834d203dd8994994a9feaa5af152c039b6023c2cf8499c19b1094.svg

La stringa (opzionale) che appare come terzo parametro (se non specificata, disegna una linea blu) descrive il colore, un eventuale marker e lo stile della linea in un unico parametro. È possibile definire i colori comuni con le lettere seguenti:

  • b: blue

  • g: green

  • r: red

  • c: cyan

  • m: magenta

  • y: yellow

  • k: black

  • w: white

Il parametro successivo, se presente, rappresenta il tipo di linea e l’eventuale punto (eventualmente entrambi, se presenti). I simboli corrispondenti sono:

  • -: solid line style

  • –: dashed line style

  • -.: dashed-dotted line style

  • :: dotted line style

  • .: point marker

  • ,: pixel marker

  • o: circle marker

  • v: triangle down marker

  • ^: triangle up marker

  • <: triangle left marker

  • s: square marker

  • p: pentagon marker

  • *: star marker

  • h: hexagon marker

  • +: plus marker

  • x: x marker

  • D: diamond marker

  • |: vertical line marker

  • _: horizonthal line marker

Alcuni dei possibili parametri opzionali che è possibile passare alla funzione plot sono:

  • alpha: trasparenza della linea (float: 0.0 = trasparente, 1.0 = opaca)

  • color (o “c”): colore della linea

  • linestyle (o “ls”): stile della linea

  • linewidth (o “lw”): larghezza della linea (float)

  • marker: tipo di marker

  • markersize (o “ms”): dimensione del marker (float)

  • markevery: ogni quanti punti mettere un marker (ma si possono specificare anche markers singoli, ecc.)

Esempio:

fig, ax = plt.subplots()
ax.plot(x, z, ls="-", lw=1.0, marker="x", markersize=10.0, color="y", markevery=(10))
_ = ax.plot(x, y, linestyle="-", linewidth=2.0, color="b", marker="x", markevery=(10))
_images/b56c096e66c10a1bae0945e3146bc010295d0eb28bf331ce0e348f52afa5fe96.svg

7.2. Notazione plt.subplots()#

Il modo prescritto per creare una figura con un singolo grafico usa la notazione plt.subplots(). In precedenza abbiamo usato l’istruzione fig, ax = plt.subplots(). Non avendo passato alcun argomento a plt.subplots() vengono usati gli argomenti di default. La chiamata predefinita è subplots(nrows=1, ncols=1); di conseguenza, creiamo un singolo grafico, come indicato sopra.

Consideriamo ora un caso in cui vogliamo creare due grafici arrangiati orizzontalmente. Definiamo delle coordinate.

x1 = [1, 2, 3, 4, 5]
y1 = [11, 22, 33, 44, 55]
x2 = [2, 3, 4, 5, 6]
y2 = [77, 66, 55, 44, 33]

Nell’istruzione seguente, si notino gli argomenti nrows=1 e ncols=2, insieme all’uso di ax1 e ax2.

fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(8, 3.5))

ax1.scatter(x=x1, y=y1, marker="o", c="r", edgecolor="b")
ax1.set_title("$y_1$ in funzione di $x_1$")
ax1.set_xlabel("$x_1$")
ax1.set_ylabel("$y_1$")

ax2.scatter(x=x2, y=y2, marker="o", c="b", edgecolor="b")
ax2.set_title("$y_2$ in funzione di $x_2$")
ax2.set_xlabel("$x_2$")
ax2.set_ylabel("$y_2$")
Text(0, 0.5, '$y_2$')
_images/a4e7e74924ef1d0507688477041865726d03940e28a0628b71c0bff9c214261e.svg

Facciamo un altro esempio usando i dati penguins.csv.

df = pd.read_csv('data/penguins.csv')
df.dropna(inplace=True)
fig, ((ax0, ax1), (ax2, ax3)) = plt.subplots(nrows=2, ncols=2, figsize=(9, 6))

ax0.hist(df["bill_depth_mm"], 10, density=True)
ax0.set_title('Bill depth (mm)')

ax1.hist(df["bill_length_mm"], 10, density=True)
ax1.set_title('Bill length (mm)')

ax2.scatter(x=df["bill_length_mm"],  y=df["bill_depth_mm"], alpha=0.4)
ax2.set_title('Bill depth as a function of bill length')

ax3.boxplot(df["body_mass_g"])
ax3.set_title('Body mass (g)')
ax3.set_xlabel("")

fig.tight_layout() # handle overlaps
_images/4452ee77c5b79ecb720f9a79392357945e518e2b53128d3751a7c0784101ccb1.svg

7.3. Watermark#

%load_ext watermark
%watermark -n -u -v -iv -w
Last updated: Sat Jun 17 2023

Python implementation: CPython
Python version       : 3.11.3
IPython version      : 8.12.0

numpy     : 1.24.3
matplotlib: 3.7.1
arviz     : 0.15.1
pandas    : 1.5.3
seaborn   : 0.12.2

Watermark: 2.3.1