Hinweis
Zum Ende springen, um den vollständigen Beispielcode herunterzuladen.
Komplexe und semantische Figurenzusammensetzung (subplot_mosaic)#
Das Anordnen von Achsen in einer Figur in einem nicht-uniformen Gitter kann sowohl mühsam als auch umständlich sein. Für dichte, gleichmäßige Gitter haben wir Figure.subplots, aber für komplexere Layouts, wie Achsen, die sich über mehrere Spalten/Zeilen des Layouts erstrecken oder einige Bereiche der Figur leer lassen, können Sie gridspec.GridSpec (siehe Anordnung mehrerer Achsen in einer Figur) verwenden oder Ihre Achsen manuell platzieren. Figure.subplot_mosaic zielt darauf ab, eine Schnittstelle bereitzustellen, um Ihre Achsen visuell (als ASCII-Art oder verschachtelte Listen) anzuordnen, um diesen Prozess zu rationalisieren.
Diese Schnittstelle unterstützt naturgemäß die Benennung Ihrer Achsen. Figure.subplot_mosaic gibt ein Wörterbuch zurück, das auf den Bezeichnungen basiert, die zur Anordnung der Figur verwendet werden. Durch die Rückgabe von Datenstrukturen mit Namen ist es einfacher, Plotting-Code zu schreiben, der unabhängig vom Figure-Layout ist.
Dies ist inspiriert von einem vorgeschlagenen MEP und der patchwork-Bibliothek für R. Obwohl wir den Stil der Operatorüberladung nicht implementieren, bieten wir eine Python-konforme API zur Angabe von (verschachtelten) Achsen-Layouts.
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)
Wenn wir ein 2x2-Gitter wünschen, können wir Figure.subplots verwenden, das ein 2D-Array von axes.Axes zurückgibt, das wir zur Durchführung unserer Plotting-Aufgaben indizieren können.
np.random.seed(19680801)
hist_data = np.random.randn(1_500)
fig = plt.figure(layout="constrained")
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)},
)

Mit Figure.subplot_mosaic können wir dasselbe Mosaik erstellen, aber den Achsen semantische Namen geben
fig = plt.figure(layout="constrained")
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)

Ein wesentlicher Unterschied zwischen Figure.subplots und Figure.subplot_mosaic ist der Rückgabewert. Während ersteres ein Array für den Indexzugriff zurückgibt, gibt letzteres ein Wörterbuch zurück, das die Bezeichnungen auf die erstellten axes.Axes-Instanzen abbildet.
print(ax_dict)
{'bar': <Axes: label='bar'>, 'plot': <Axes: label='plot'>, 'hist': <Axes: label='hist'>, 'image': <Axes: label='image'>}
String-Kurzschreibweise#
Indem wir unsere Achsenbezeichnungen auf einzelne Zeichen beschränken, können wir die gewünschten Achsen als "ASCII-Art" "zeichnen". Das Folgende
mosaic = """
AB
CD
"""
ergibt uns 4 Achsen, die in einem 2x2-Gitter angeordnet sind und dasselbe Figurenmosaik wie oben erzeugen (aber jetzt mit {"A", "B", "C", "D"} statt {"bar", "plot", "hist", "image"} beschriftet).
fig = plt.figure(layout="constrained")
ax_dict = fig.subplot_mosaic(mosaic)
identify_axes(ax_dict)

Alternativ können Sie die kompaktere String-Notation verwenden
mosaic = "AB;CD"
ergibt Ihnen dieselbe Komposition, wobei das ';' als Zeilentrenner anstelle eines Zeilenumbruchs verwendet wird.
fig = plt.figure(layout="constrained")
ax_dict = fig.subplot_mosaic(mosaic)
identify_axes(ax_dict)

Achsen, die sich über mehrere Zeilen/Spalten erstrecken#
Etwas, das wir mit Figure.subplot_mosaic tun können, was wir mit Figure.subplots nicht können, ist anzugeben, dass sich eine Achse über mehrere Zeilen oder Spalten erstrecken soll.
Wenn wir unsere vier Achsen neu anordnen wollen, sodass "C" eine horizontale Spanne unten und "D" eine vertikale Spanne rechts ist, würden wir Folgendes tun:
axd = plt.figure(layout="constrained").subplot_mosaic(
"""
ABD
CCD
"""
)
identify_axes(axd)

Wenn wir nicht alle Flächen in der Figur mit Achsen füllen wollen, können wir einige Flächen im Gitter als leer angeben
axd = plt.figure(layout="constrained").subplot_mosaic(
"""
A.C
BBB
.D.
"""
)
identify_axes(axd)

Wenn wir lieber ein anderes Zeichen (anstelle eines Punktes '.') verwenden möchten, um den leeren Platz zu markieren, können wir *empty_sentinel* verwenden, um das zu verwendende Zeichen anzugeben.
axd = plt.figure(layout="constrained").subplot_mosaic(
"""
aX
Xb
""",
empty_sentinel="X",
)
identify_axes(axd)

Intern hat die Bedeutung der verwendeten Buchstaben keine Bedeutung, jeder Unicode-Codepunkt ist gültig!
axd = plt.figure(layout="constrained").subplot_mosaic(
"""αб
ℝ☢"""
)
identify_axes(axd)

Es wird nicht empfohlen, Leerzeichen als Bezeichnungen oder als leere Sentinel bei der String-Kurzschreibweise zu verwenden, da diese während der Verarbeitung der Eingabe gestrippt werden können.
Steuerung der Mosaikerstellung#
Diese Funktion basiert auf gridspec und Sie können Schlüsselwortargumente an das zugrunde liegende gridspec.GridSpec übergeben (wie bei Figure.subplots).
In diesem Fall möchten wir die Eingabe zur Spezifikation des Layouts verwenden, aber die relativen Breiten der Zeilen/Spalten festlegen. Zur Bequemlichkeit sind die *height_ratios*- und *width_ratios*-Argumente von gridspec.GridSpec in der Aufrufsequenz von Figure.subplot_mosaic verfügbar.
axd = plt.figure(layout="constrained").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)

Andere Schlüsselwörter von gridspec.GridSpec können über *gridspec_kw* übergeben werden. Verwenden Sie zum Beispiel die Schlüsselwortargumente {*left*, *right*, *bottom*, *top*}, um das Gesamtmosaik zu positionieren, um mehrere Versionen desselben Mosaiks in einer Figur zu platzieren.
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)

Alternativ können Sie die Sub-Figure-Funktionalität verwenden
mosaic = """AA
BC"""
fig = plt.figure(layout="constrained")
left, right = fig.subfigures(nrows=1, ncols=2)
axd = left.subplot_mosaic(mosaic)
identify_axes(axd)
axd = right.subplot_mosaic(mosaic)
identify_axes(axd)

Steuerung der Subplot-Erstellung#
Wir können auch Argumente übergeben, die zur Erstellung der Subplots verwendet werden (wiederum wie bei Figure.subplots), die für alle erstellten Achsen gelten.
axd = plt.figure(layout="constrained").subplot_mosaic(
"AB", subplot_kw={"projection": "polar"}
)
identify_axes(axd)

Schlüsselwortargumente für Subplots pro Achse#
Wenn Sie die Parameter, die an jeden Subplot übergeben werden, individuell steuern müssen, verwenden Sie *per_subplot_kw*, um eine Zuordnung zwischen den Achsen-Identifikatoren (oder Tupeln von Achsen-Identifikatoren) zu Wörterbüchern mit Schlüsselwörtern zu übergeben, die weitergegeben werden sollen.
Hinzugefügt in Version 3.7.
fig, axd = plt.subplot_mosaic(
"AB;CD",
per_subplot_kw={
"A": {"projection": "polar"},
("C", "D"): {"xscale": "log"}
},
)
identify_axes(axd)

Wenn das Layout mit der String-Kurzschreibweise angegeben wird, wissen wir, dass die Achsenbezeichnungen ein Zeichen lang sein werden, und können längere Zeichenfolgen in *per_subplot_kw* eindeutig interpretieren, um eine Menge von Achsen anzugeben, auf die die Schlüsselwörter angewendet werden sollen.
fig, axd = plt.subplot_mosaic(
"AB;CD",
per_subplot_kw={
"AD": {"projection": "polar"},
"BC": {"facecolor": ".9"}
},
)
identify_axes(axd)

Wenn *subplot_kw* und *per_subplot_kw* zusammen verwendet werden, werden sie zusammengeführt, wobei *per_subplot_kw* Vorrang hat.
axd = plt.figure(layout="constrained").subplot_mosaic(
"AB;CD",
subplot_kw={"facecolor": "xkcd:tangerine"},
per_subplot_kw={
"B": {"facecolor": "xkcd:water blue"},
"D": {"projection": "polar", "facecolor": "w"},
}
)
identify_axes(axd)

Verschachtelte Listeneingabe#
Alles, was wir mit der String-Kurzschreibweise tun können, können wir auch bei der Eingabe einer Liste tun (intern konvertieren wir die String-Kurzschreibweise in eine verschachtelte Liste), zum Beispiel unter Verwendung von Spannen, Leerstellen und *gridspec_kw*.
axd = plt.figure(layout="constrained").subplot_mosaic(
[
["main", "zoom"],
["main", "BLANK"],
],
empty_sentinel="BLANK",
width_ratios=[2, 1],
)
identify_axes(axd)

Zusätzlich können wir bei Verwendung der Listeneingabe verschachtelte Mosaike spezifizieren. Jedes Element der inneren Liste kann eine weitere Menge von verschachtelten Listen sein.
inner = [
["inner A"],
["inner B"],
]
outer_nested_mosaic = [
["main", inner],
["bottom", "bottom"],
]
axd = plt.figure(layout="constrained").subplot_mosaic(
outer_nested_mosaic, empty_sentinel=None
)
identify_axes(axd, fontsize=36)

Wir können auch ein 2D-NumPy-Array übergeben, um Dinge wie folgt zu tun:

Gesamtlaufzeit des Skripts: (0 Minuten 14,288 Sekunden)