Nota
Fare clic qui per scaricare il codice di esempio completo
Disporre più assi in una figura #
Spesso si desidera più di un Asse su una figura alla volta, di solito organizzato in una griglia regolare. Matplotlib ha una varietà di strumenti per lavorare con griglie di assi che si sono evoluti nel corso della storia della libreria. Qui discuteremo gli strumenti che pensiamo che gli utenti dovrebbero usare più spesso, gli strumenti che sono alla base dell'organizzazione di Axes e menzioneremo alcuni degli strumenti meno recenti.
Nota
Matplotlib utilizza Axes per fare riferimento all'area di disegno che contiene dati, assi x e y, segni di spunta, etichette, titolo, ecc. Vedere Parti di una figura per maggiori dettagli. Un altro termine spesso utilizzato è "sottotrama", che si riferisce a un Axes che si trova in una griglia con altri oggetti Axes.
Panoramica n.
Crea combinazioni di assi a forma di griglia #
subplots
La funzione principale utilizzata per creare figure e una griglia di assi. Crea e posiziona tutti gli assi sulla figura contemporaneamente e restituisce un array di oggetti con maniglie per gli assi nella griglia. Vedi
Figure.subplots
.
o
subplot_mosaic
Un modo semplice per creare figure e una griglia di assi, con l'ulteriore flessibilità che gli assi possono anche estendersi su righe o colonne. Gli assi vengono restituiti in un dizionario etichettato anziché in un array. Vedi anche
Figure.subplot_mosaic
e Composizione di figure complesse e semantiche .
A volte è naturale avere più di un gruppo distinto di griglie Axes, nel qual caso Matplotlib ha il concetto di SubFigure
:
SubFigure
Una figura virtuale all'interno di una figura.
Strumenti sottostanti #
Alla base di questi ci sono i concetti di a GridSpec
e a SubplotSpec
:
GridSpec
Specifica la geometria della griglia in cui verrà posizionata una sottotrama. È necessario impostare il numero di righe e il numero di colonne della griglia. Facoltativamente, è possibile regolare i parametri di layout della sottotrama (ad esempio, sinistra, destra, ecc.).
SubplotSpec
Specifica la posizione della sottotrama nel dato
GridSpec
.
Aggiunta di singoli assi alla volta #
Le funzioni di cui sopra creano tutti gli assi in una singola chiamata di funzione. È anche possibile aggiungere gli assi uno alla volta, e questo era originariamente il modo in cui Matplotlib funzionava. Farlo è generalmente meno elegante e flessibile, sebbene a volte utile per il lavoro interattivo o per posizionare un Axes in una posizione personalizzata:
add_axes
Aggiunge un singolo asse in una posizione specificata da in frazioni di larghezza o altezza della figura.
[left, bottom, width, height]
subplot
oFigure.add_subplot
Aggiunge una singola sottotrama su una figura, con indicizzazione in base 1 (ereditata da Matlab). Le colonne e le righe possono essere estese specificando un intervallo di celle della griglia.
subplot2grid
Simile a
pyplot.subplot
, ma utilizza l'indicizzazione basata su 0 e l'affettatura python a due dimensioni per scegliere le celle.
Metodi di alto livello per creare griglie #
Griglia base 2x2 #
Possiamo creare una griglia di assi 2 per 2 di base utilizzando
subplots
. Restituisce Figure
un'istanza e un array di Axes
oggetti. Gli oggetti Axes possono essere utilizzati per accedere ai metodi per posizionare gli artisti sugli Axes; qui usiamo annotate
, ma altri esempi potrebbero essere plot
,
pcolormesh
, ecc.
import matplotlib.pyplot as plt
import numpy as np
fig, axs = plt.subplots(ncols=2, nrows=2, figsize=(5.5, 3.5),
layout="constrained")
# add an artist, in this case a nice label in the middle...
for row in range(2):
for col in range(2):
axs[row, col].annotate(f'axs[{row}, {col}]', (0.5, 0.5),
transform=axs[row, col].transAxes,
ha='center', va='center', fontsize=18,
color='darkgrey')
fig.suptitle('plt.subplots()')
Text(0.5, 0.9880942857142857, 'plt.subplots()')
Annoteremo molti assi, quindi incapsuliamo l'annotazione, piuttosto che avere quel grosso pezzo di codice di annotazione ogni volta che ne abbiamo bisogno:
def annotate_axes(ax, text, fontsize=18):
ax.text(0.5, 0.5, text, transform=ax.transAxes,
ha="center", va="center", fontsize=fontsize, color="darkgrey")
Lo stesso effetto può essere ottenuto con subplot_mosaic
, ma il tipo restituito è un dizionario invece di un array, dove l'utente può dare alle chiavi significati utili. Qui forniamo due liste, ciascuna delle quali rappresenta una riga e ciascun elemento della lista una chiave che rappresenta la colonna.
fig, axd = plt.subplot_mosaic([['upper left', 'upper right'],
['lower left', 'lower right']],
figsize=(5.5, 3.5), layout="constrained")
for k in axd:
annotate_axes(axd[k], f'axd["{k}"]', fontsize=14)
fig.suptitle('plt.subplot_mosaic()')
Text(0.5, 0.9880942857142857, 'plt.subplot_mosaic()')
Griglie di assi a proporzioni fisse #
Gli assi con proporzioni fisse sono comuni per le immagini o le mappe. Tuttavia, rappresentano una sfida per il layout perché vengono imposti due serie di vincoli sulla dimensione degli assi: che si adattino alla figura e che abbiano un rapporto di aspetto prestabilito. Questo porta a grandi spazi tra gli assi per impostazione predefinita:
fig, axs = plt.subplots(2, 2, layout="constrained", figsize=(5.5, 3.5))
for ax in axs.flat:
ax.set_aspect(1)
fig.suptitle('Fixed aspect Axes')
Text(0.5, 0.9880942857142857, 'Fixed aspect Axes')
Un modo per risolvere questo problema è modificare l'aspetto della figura in modo che sia vicino alle proporzioni degli assi, tuttavia ciò richiede tentativi ed errori. Matplotlib fornisce anche layout="compressed"
, che funzionerà con griglie semplici per ridurre gli spazi tra gli assi. (Il mpl_toolkits
fornisce anche ImageGrid
per ottenere un effetto simile, ma con una classe Axes non standard).
fig, axs = plt.subplots(2, 2, layout="compressed", figsize=(5.5, 3.5))
for ax in axs.flat:
ax.set_aspect(1)
fig.suptitle('Fixed aspect Axes: compressed')
Text(0.5, 0.9880942857142857, 'Fixed aspect Axes: compressed')
Assi che si estendono su righe o colonne in una griglia #
A volte vogliamo che Axes si estenda su righe o colonne della griglia. Esistono in realtà diversi modi per farlo, ma il più conveniente è probabilmente quello di utilizzare subplot_mosaic
ripetendo uno dei tasti:
fig, axd = plt.subplot_mosaic([['upper left', 'right'],
['lower left', 'right']],
figsize=(5.5, 3.5), layout="constrained")
for k in axd:
annotate_axes(axd[k], f'axd["{k}"]', fontsize=14)
fig.suptitle('plt.subplot_mosaic()')
Text(0.5, 0.9880942857142857, 'plt.subplot_mosaic()')
Vedi sotto per la descrizione di come fare la stessa cosa usando
GridSpec
o subplot2grid
.
Larghezze o altezze variabili in una griglia #
Entrambi subplots
e subplot_mosaic
consentono alle righe nella griglia di avere altezze diverse e alle colonne di avere larghezze diverse utilizzando l' argomento della parola chiave gridspec_kw . I parametri di spaziatura accettati da GridSpec
possono essere passati a subplots
e
subplot_mosaic
:
gs_kw = dict(width_ratios=[1.4, 1], height_ratios=[1, 2])
fig, axd = plt.subplot_mosaic([['upper left', 'right'],
['lower left', 'right']],
gridspec_kw=gs_kw, figsize=(5.5, 3.5),
layout="constrained")
for k in axd:
annotate_axes(axd[k], f'axd["{k}"]', fontsize=14)
fig.suptitle('plt.subplot_mosaic()')
Text(0.5, 0.9880942857142857, 'plt.subplot_mosaic()')
Layout degli assi nidificati #
A volte è utile avere due o più griglie di Assi che potrebbero non aver bisogno di essere correlate tra loro. Il modo più semplice per farlo è usare Figure.subfigures
. Si noti che i layout delle sottofigure sono indipendenti, quindi i dorsi degli assi in ogni sottofigura non sono necessariamente allineati. Vedi sotto per un modo più dettagliato per ottenere lo stesso effetto con GridSpecFromSubplotSpec
.
fig = plt.figure(layout="constrained")
subfigs = fig.subfigures(1, 2, wspace=0.07, width_ratios=[1.5, 1.])
axs0 = subfigs[0].subplots(2, 2)
subfigs[0].set_facecolor('0.9')
subfigs[0].suptitle('subfigs[0]\nLeft side')
subfigs[0].supxlabel('xlabel for subfigs[0]')
axs1 = subfigs[1].subplots(3, 1)
subfigs[1].suptitle('subfigs[1]')
subfigs[1].supylabel('ylabel for subfigs[1]')
Text(0.016867713730569944, 0.5, 'ylabel for subfigs[1]')
È anche possibile nidificare gli assi utilizzando subplot_mosaic
elenchi nidificati. Questo metodo non utilizza le sottofigure, come sopra, quindi non ha la possibilità di aggiungere per sottofigura suptitle
e supxlabel
, ecc. Piuttosto è un comodo wrapper attorno al subgridspec
metodo descritto di seguito.
Metodi griglia di basso livello e avanzati #
Internamente, la disposizione di una griglia di assi è controllata creando istanze di GridSpec
e SubplotSpec
. GridSpec definisce una griglia di celle (possibilmente non uniforme). L'indicizzazione in GridSpec restituisce un SubplotSpec che copre una o più celle della griglia e può essere utilizzato per specificare la posizione di un Axes.
Gli esempi seguenti mostrano come utilizzare i metodi di basso livello per disporre gli assi utilizzando gli oggetti GridSpec .
Griglia base 2x2 #
Possiamo realizzare una griglia 2x2 nello stesso modo di
:plt.subplots(2, 2)
fig = plt.figure(figsize=(5.5, 3.5), layout="constrained")
spec = fig.add_gridspec(ncols=2, nrows=2)
ax0 = fig.add_subplot(spec[0, 0])
annotate_axes(ax0, 'ax0')
ax1 = fig.add_subplot(spec[0, 1])
annotate_axes(ax1, 'ax1')
ax2 = fig.add_subplot(spec[1, 0])
annotate_axes(ax2, 'ax2')
ax3 = fig.add_subplot(spec[1, 1])
annotate_axes(ax3, 'ax3')
fig.suptitle('Manually added subplots using add_gridspec')
Text(0.5, 0.9880942857142857, 'Manually added subplots using add_gridspec')
Assi che attraversano righe o griglie in una griglia #
Possiamo indicizzare l' array delle specifiche utilizzando la sintassi della sezione NumPy
e i nuovi assi si estenderanno sulla sezione. Questo sarebbe lo stesso di :fig, axd = plt.subplot_mosaic([['ax0', 'ax0'], ['ax1', 'ax2']], ...)
fig = plt.figure(figsize=(5.5, 3.5), layout="constrained")
spec = fig.add_gridspec(2, 2)
ax0 = fig.add_subplot(spec[0, :])
annotate_axes(ax0, 'ax0')
ax10 = fig.add_subplot(spec[1, 0])
annotate_axes(ax10, 'ax10')
ax11 = fig.add_subplot(spec[1, 1])
annotate_axes(ax11, 'ax11')
fig.suptitle('Manually added subplots, spanning a column')
Text(0.5, 0.9880942857142857, 'Manually added subplots, spanning a column')
Regolazioni manuali a un layout GridSpec #
Quando un GridSpec viene utilizzato in modo esplicito, è possibile regolare i parametri di layout delle sottotrame create da GridSpec . Nota che questa opzione non è compatibile con constrained_layout
o
Figure.tight_layout
che entrambi ignorano sinistra e destra e regolano le dimensioni della sottotrama per riempire la figura. Di solito tale posizionamento manuale richiede iterazioni per fare in modo che le etichette di spunta degli assi non si sovrappongano agli assi.
Questi parametri di spaziatura possono anche essere passati a subplots
e
subplot_mosaic
come argomento gridspec_kw .
fig = plt.figure(layout=None, facecolor='0.9')
gs = fig.add_gridspec(nrows=3, ncols=3, left=0.05, right=0.75,
hspace=0.1, wspace=0.05)
ax0 = fig.add_subplot(gs[:-1, :])
annotate_axes(ax0, 'ax0')
ax1 = fig.add_subplot(gs[-1, :-1])
annotate_axes(ax1, 'ax1')
ax2 = fig.add_subplot(gs[-1, -1])
annotate_axes(ax2, 'ax2')
fig.suptitle('Manual gridspec with right=0.75')
Text(0.5, 0.98, 'Manual gridspec with right=0.75')
Layout nidificati con SubplotSpec #
È possibile creare un layout nidificato simile subfigures
all'utilizzo
di subgridspec
. Qui le spine degli assi sono
allineate.
Nota che questo è disponibile anche dal più dettagliato
gridspec.GridSpecFromSubplotSpec
.
fig = plt.figure(layout="constrained")
gs0 = fig.add_gridspec(1, 2)
gs00 = gs0[0].subgridspec(2, 2)
gs01 = gs0[1].subgridspec(3, 1)
for a in range(2):
for b in range(2):
ax = fig.add_subplot(gs00[a, b])
annotate_axes(ax, f'axLeft[{a}, {b}]', fontsize=10)
if a == 1 and b == 1:
ax.set_xlabel('xlabel')
for a in range(3):
ax = fig.add_subplot(gs01[a])
annotate_axes(ax, f'axRight[{a}, {b}]')
if a == 2:
ax.set_ylabel('ylabel')
fig.suptitle('nested gridspecs')
Text(0.5, 0.99131875, 'nested gridspecs')
Ecco un esempio più sofisticato di GridSpec annidato : creiamo una griglia 4x4 esterna con ogni cella contenente una griglia interna 3x3 di assi. Delineamo la griglia 4x4 esterna nascondendo le spine appropriate in ciascuna delle griglie 3x3 interne.
def squiggle_xy(a, b, c, d, i=np.arange(0.0, 2*np.pi, 0.05)):
return np.sin(i*a)*np.cos(i*b), np.sin(i*c)*np.cos(i*d)
fig = plt.figure(figsize=(8, 8), constrained_layout=False)
outer_grid = fig.add_gridspec(4, 4, wspace=0, hspace=0)
for a in range(4):
for b in range(4):
# gridspec inside gridspec
inner_grid = outer_grid[a, b].subgridspec(3, 3, wspace=0, hspace=0)
axs = inner_grid.subplots() # Create all subplots for the inner grid.
for (c, d), ax in np.ndenumerate(axs):
ax.plot(*squiggle_xy(a + 1, b + 1, c + 1, d + 1))
ax.set(xticks=[], yticks=[])
# show only the outside spines
for ax in fig.get_axes():
ss = ax.get_subplotspec()
ax.spines.top.set_visible(ss.is_first_row())
ax.spines.bottom.set_visible(ss.is_last_row())
ax.spines.left.set_visible(ss.is_first_col())
ax.spines.right.set_visible(ss.is_last_col())
plt.show()
Altre letture #
Maggiori dettagli sul mosaico della sottotrama .
Ulteriori dettagli sul layout vincolato , utilizzato per allineare la spaziatura nella maggior parte di questi esempi.
Riferimenti
L'uso delle seguenti funzioni, metodi, classi e moduli è mostrato in questo esempio:
Tempo di esecuzione totale dello script: (0 minuti 13,006 secondi)