Nota
Fare clic qui per scaricare il codice di esempio completo
Composizione di figure complesse e semantiche #
Avvertimento
Questo tutorial documenta l'API sperimentale/provvisoria. Stiamo rilasciando questo in v3.3 per ottenere il feedback degli utenti. Potremmo apportare modifiche sostanziali nelle versioni future senza preavviso.
Disporre gli assi in una figura in una griglia non uniforme può essere noioso e prolisso. Per griglie dense e uniformi abbiamo Figure.subplots
ma per layout più complessi, come Assi che si estendono su più colonne/righe del layout o lasciano vuote alcune aree della Figura, puoi usare
gridspec.GridSpec
(vedi Disporre più Assi in una Figura ) o posizionare manualmente il tuo assi. Figure.subplot_mosaic
mira a fornire un'interfaccia per disporre visivamente i tuoi assi (come arte ASCII o elenchi nidificati) per semplificare questo processo.
Questa interfaccia supporta naturalmente la denominazione degli assi.
Figure.subplot_mosaic
restituisce un dizionario digitato sulle etichette utilizzate per disporre la figura. Restituendo strutture dati con nomi, è più semplice scrivere codice di tracciamento indipendente dal layout Figure.
Questo è ispirato da un MEP proposto e dalla libreria patchwork per R. Sebbene non implementiamo lo stile di sovraccarico dell'operatore, forniamo un'API Pythonic per specificare i layout degli assi (nidificati).
import matplotlib.pyplot as plt
import numpy as np
# Helper function used for visualization in the following examples
def identify_axes(ax_dict, fontsize=48):
"""
Helper to identify the Axes in the examples below.
Draws the label in a large font in the center of the Axes.
Parameters
----------
ax_dict : dict[str, Axes]
Mapping between the title / label and the Axes.
fontsize : int, optional
How big the label should be.
"""
kw = dict(ha="center", va="center", fontsize=fontsize, color="darkgrey")
for k, ax in ax_dict.items():
ax.text(0.5, 0.5, k, transform=ax.transAxes, **kw)
Se vogliamo una griglia 2x2 possiamo usare Figure.subplots
which restituisce un array 2D di axes.Axes
cui possiamo indicizzare per fare il nostro tracciato.
np.random.seed(19680801)
hist_data = np.random.randn(1_500)
fig = plt.figure(constrained_layout=True)
ax_array = fig.subplots(2, 2, squeeze=False)
ax_array[0, 0].bar(["a", "b", "c"], [5, 7, 9])
ax_array[0, 1].plot([1, 2, 3])
ax_array[1, 0].hist(hist_data, bins="auto")
ax_array[1, 1].imshow([[1, 2], [2, 1]])
identify_axes(
{(j, k): a for j, r in enumerate(ax_array) for k, a in enumerate(r)},
)
Usando Figure.subplot_mosaic
possiamo produrre lo stesso mosaico ma dare agli assi nomi semantici
fig = plt.figure(constrained_layout=True)
ax_dict = fig.subplot_mosaic(
[
["bar", "plot"],
["hist", "image"],
],
)
ax_dict["bar"].bar(["a", "b", "c"], [5, 7, 9])
ax_dict["plot"].plot([1, 2, 3])
ax_dict["hist"].hist(hist_data)
ax_dict["image"].imshow([[1, 2], [2, 1]])
identify_axes(ax_dict)
Una differenza fondamentale tra Figure.subplots
e
Figure.subplot_mosaic
è il valore restituito. Mentre il primo restituisce un array per l'accesso all'indice, il secondo restituisce un dizionario che mappa le etichette alle axes.Axes
istanze create
print(ax_dict)
{'bar': <AxesSubplot: label='bar'>, 'plot': <AxesSubplot: label='plot'>, 'hist': <AxesSubplot: label='hist'>, 'image': <AxesSubplot: label='image'>}
Corda abbreviata #
Limitando le nostre etichette degli assi a singoli caratteri possiamo "disegnare" gli assi che vogliamo come "arte ASCII". Il seguente
mosaic = """
AB
CD
"""
ci darà 4 assi disposti in una griglia 2x2 e genera lo stesso mosaico di figure come sopra (ma ora etichettato con anziché ).{"A", "B", "C",
"D"}
{"bar", "plot", "hist", "image"}
fig = plt.figure(constrained_layout=True)
ax_dict = fig.subplot_mosaic(mosaic)
identify_axes(ax_dict)
In alternativa, puoi usare la notazione per stringhe più compatta
mosaic = "AB;CD"
ti darà la stessa composizione, dove ";"
viene usato come separatore di riga invece di newline.
fig = plt.figure(constrained_layout=True)
ax_dict = fig.subplot_mosaic(mosaic)
identify_axes(ax_dict)
Assi che si estendono su più righe/colonne #
Qualcosa che possiamo fare con Figure.subplot_mosaic
ciò che non puoi fare Figure.subplots
è specificare che un Axes dovrebbe estendersi su più righe o colonne.
Se vogliamo riorganizzare i nostri quattro assi in modo che "C"
siano una campata orizzontale in basso e "D"
una campata verticale a destra, faremmo
axd = plt.figure(constrained_layout=True).subplot_mosaic(
"""
ABD
CCD
"""
)
identify_axes(axd)
Se non vogliamo riempire tutti gli spazi della Figura con Assi, possiamo specificare che alcuni spazi della griglia siano vuoti
axd = plt.figure(constrained_layout=True).subplot_mosaic(
"""
A.C
BBB
.D.
"""
)
identify_axes(axd)
Se preferiamo utilizzare un altro carattere (piuttosto che un "."
punto) per contrassegnare lo spazio vuoto, possiamo utilizzare empty_sentinel per specificare il carattere da utilizzare.
axd = plt.figure(constrained_layout=True).subplot_mosaic(
"""
aX
Xb
""",
empty_sentinel="X",
)
identify_axes(axd)
Internamente non c'è alcun significato associato alle lettere che usiamo, qualsiasi punto di codice Unicode è valido!
axd = plt.figure(constrained_layout=True).subplot_mosaic(
"""αб
ℝ☢"""
)
identify_axes(axd)
Non è consigliabile utilizzare lo spazio bianco come etichetta o sentinella vuota con la stringa abbreviata perché potrebbe essere rimossa durante l'elaborazione dell'input.
Controllo della creazione di mosaici e sottotrame #
Questa funzionalità è basata su gridspec
e puoi passare gli argomenti della parola chiave al sottostante gridspec.GridSpec
(lo stesso di Figure.subplots
).
In questo caso vogliamo utilizzare l'input per specificare la disposizione, ma impostare le larghezze relative delle righe/colonne tramite gridspec_kw .
axd = plt.figure(constrained_layout=True).subplot_mosaic(
"""
.a.
bAc
.d.
""",
# set the height ratios between the rows
height_ratios=[1, 3.5, 1],
# set the width ratios between the columns
width_ratios=[1, 3.5, 1],
)
identify_axes(axd)
Oppure usa gli argomenti della parola chiave { left , right , bottom , top } per posizionare il mosaico complessivo per inserire più versioni dello stesso mosaico in una figura
mosaic = """AA
BC"""
fig = plt.figure()
axd = fig.subplot_mosaic(
mosaic,
gridspec_kw={
"bottom": 0.25,
"top": 0.95,
"left": 0.1,
"right": 0.5,
"wspace": 0.5,
"hspace": 0.5,
},
)
identify_axes(axd)
axd = fig.subplot_mosaic(
mosaic,
gridspec_kw={
"bottom": 0.05,
"top": 0.75,
"left": 0.6,
"right": 0.95,
"wspace": 0.5,
"hspace": 0.5,
},
)
identify_axes(axd)
In alternativa, puoi utilizzare la funzionalità sub-Figure:
mosaic = """AA
BC"""
fig = plt.figure(constrained_layout=True)
left, right = fig.subfigures(nrows=1, ncols=2)
axd = left.subplot_mosaic(mosaic)
identify_axes(axd)
axd = right.subplot_mosaic(mosaic)
identify_axes(axd)
Possiamo anche passare attraverso argomenti usati per creare le sottotrame (di nuovo, lo stesso di Figure.subplots
).
axd = plt.figure(constrained_layout=True).subplot_mosaic(
"AB", subplot_kw={"projection": "polar"}
)
identify_axes(axd)
Ingresso elenco nidificato #
Tutto ciò che possiamo fare con la stringa abbreviata lo possiamo fare anche quando passiamo una lista (internamente convertiamo la stringa abbreviata in una lista nidificata), ad esempio usando span, spazi vuoti e gridspec_kw :
axd = plt.figure(constrained_layout=True).subplot_mosaic(
[
["main", "zoom"],
["main", "BLANK"],
],
empty_sentinel="BLANK",
width_ratios=[2, 1],
)
identify_axes(axd)
Inoltre, utilizzando l'input list possiamo specificare i mosaici nidificati. Qualsiasi elemento dell'elenco interno può essere un altro insieme di elenchi nidificati:
inner = [
["inner A"],
["inner B"],
]
outer_nested_mosaic = [
["main", inner],
["bottom", "bottom"],
]
axd = plt.figure(constrained_layout=True).subplot_mosaic(
outer_nested_mosaic, empty_sentinel=None
)
identify_axes(axd, fontsize=36)
Possiamo anche passare un array NumPy 2D per fare cose come
Tempo di esecuzione totale dello script: (0 minuti 9,170 secondi)