Mehrere Achsen in einer Figur anordnen #

Oftmals werden mehr als eine Axt auf einer Figur gleichzeitig benötigt, normalerweise in einem regelmäßigen Raster organisiert. Matplotlib verfügt über eine Vielzahl von Tools für die Arbeit mit Rastern von Axes, die sich im Laufe der Geschichte der Bibliothek entwickelt haben. Hier werden wir die Tools besprechen, von denen wir glauben, dass Benutzer sie am häufigsten verwenden sollten, die Tools, die die Organisation von Axes untermauern, und einige der älteren Tools erwähnen.

Notiz

Matplotlib verwendet Axes , um auf den Zeichenbereich zu verweisen, der Daten, x- und y-Achse, Ticks, Beschriftungen, Titel usw. enthält. Siehe Teile einer Abbildung für weitere Details. Ein anderer häufig verwendeter Begriff ist "Subplot", der sich auf ein Axes bezieht, das sich in einem Raster mit anderen Axes-Objekten befindet.

Übersicht #

Erstellen Sie gitterförmige Kombinationen von Achsen #

subplots

Die primäre Funktion zum Erstellen von Figuren und einem Achsenraster. Es erstellt und platziert alle Achsen gleichzeitig auf der Figur und gibt ein Objektarray mit Griffen für die Achsen im Raster zurück. Siehe Figure.subplots.

oder

subplot_mosaic

Eine einfache Möglichkeit, Figuren und ein Achsenraster zu erstellen, mit der zusätzlichen Flexibilität, dass Achsen auch Zeilen oder Spalten überspannen können. Die Achsen werden in einem beschrifteten Wörterbuch anstelle eines Arrays zurückgegeben. Siehe auch Figure.subplot_mosaicKomplexe und semantische Figurenkomposition .

Manchmal ist es natürlich, mehr als eine unterschiedliche Gruppe von Achsengittern zu haben, in diesem Fall hat Matplotlib das Konzept von SubFigure:

SubFigure

Eine virtuelle Figur in einer Figur.

Zugrunde liegende Werkzeuge #

Dahinter stehen die Konzepte von a GridSpecund a SubplotSpec:

GridSpec

Gibt die Geometrie des Rasters an, in dem ein Nebenplot platziert wird. Die Anzahl der Zeilen und Spalten des Rasters muss eingestellt werden. Optional können die Teilplot-Layoutparameter (z. B. links, rechts usw.) angepasst werden.

SubplotSpec

Gibt den Ort der Nebenhandlung in der angegebenen GridSpec.

Einzelne Achsen gleichzeitig hinzufügen #

Die obigen Funktionen erstellen alle Achsen in einem einzigen Funktionsaufruf. Es ist auch möglich, Achsen einzeln hinzuzufügen, und so hat Matplotlib ursprünglich funktioniert. Dies ist im Allgemeinen weniger elegant und flexibel, aber manchmal nützlich für interaktives Arbeiten oder um eine Axt an einem benutzerdefinierten Ort zu platzieren:

add_axes

Fügt eine einzelne Achse an einer durch angegebenen Position in Bruchteilen der Breite oder Höhe der Figur hinzu.[left, bottom, width, height]

subplotoderFigure.add_subplot

Fügt einer Figur einen einzelnen Subplot hinzu, mit 1-basierter Indizierung (geerbt von Matlab). Spalten und Zeilen können überspannt werden, indem ein Bereich von Gitterzellen angegeben wird.

subplot2grid

Ähnlich wie pyplot.subplot, verwendet aber 0-basierte Indizierung und Zwei-D-Python-Slicing, um Zellen auszuwählen.

High-Level-Methoden zum Erstellen von Gittern #

Einfaches 2x2-Raster #

Wir können ein einfaches 2-mal-2-Achsraster erstellen, indem wir verwenden subplots. Es gibt eine Figure Instanz und ein Array von AxesObjekten zurück. Die Axes-Objekte können verwendet werden, um auf Methoden zuzugreifen, um Künstler auf den Axes zu platzieren; hier verwenden wir annotate, aber andere Beispiele könnten plot, pcolormesh, usw. sein.

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()')
plt.subplots()
Text(0.5, 0.9880942857142857, 'plt.subplots()')

Wir werden viele Achsen annotieren, also kapseln wir die Annotation, anstatt dieses große Stück Annotationscode jedes Mal zu haben, wenn wir es brauchen:

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")

Der gleiche Effekt kann mit erreicht werden subplot_mosaic, aber der Rückgabetyp ist ein Wörterbuch anstelle eines Arrays, in dem der Benutzer den Schlüsseln nützliche Bedeutungen geben kann. Hier stellen wir zwei Listen bereit, wobei jede Liste eine Zeile darstellt und jedes Element in der Liste einen Schlüssel, der die Spalte darstellt.

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()')
plt.subplot_mosaic()
Text(0.5, 0.9880942857142857, 'plt.subplot_mosaic()')

Gitter mit festem Seitenverhältnis Achsen #

Achsen mit festem Seitenverhältnis sind für Bilder oder Karten üblich. Sie stellen jedoch eine Herausforderung für das Layout dar, da der Größe der Achsen zwei Arten von Beschränkungen auferlegt werden – dass sie in die Figur passen und dass sie ein festgelegtes Seitenverhältnis haben. Dies führt standardmäßig zu großen Lücken zwischen Achsen:

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')
Äxte mit festem Aspekt
Text(0.5, 0.9880942857142857, 'Fixed aspect Axes')

Eine Möglichkeit, dies zu beheben, besteht darin, das Seitenverhältnis der Figur so zu ändern, dass es dem Seitenverhältnis der Äxte nahekommt, dies erfordert jedoch Versuch und Irrtum. Matplotlib liefert auch layout="compressed", das mit einfachen Gittern arbeitet, um die Lücken zwischen den Achsen zu verringern. (Der mpl_toolkitssieht auch vor ImageGrid, einen ähnlichen Effekt zu erzielen, aber mit einer nicht standardmäßigen Axes-Klasse).

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')
Äxte mit festem Aspekt: ​​komprimiert
Text(0.5, 0.9880942857142857, 'Fixed aspect Axes: compressed')

Achsen, die Zeilen oder Spalten in einem Raster überspannen #

Manchmal möchten wir, dass Achsen Zeilen oder Spalten des Rasters überspannen. Es gibt tatsächlich mehrere Möglichkeiten, dies zu erreichen, aber am bequemsten ist es wahrscheinlich, subplot_mosaiceine der Tasten zu wiederholen:

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()')
plt.subplot_mosaic()
Text(0.5, 0.9880942857142857, 'plt.subplot_mosaic()')

Unten finden Sie eine Beschreibung, wie Sie dasselbe mit GridSpecoder tun können subplot2grid.

Variable Breiten oder Höhen in einem Raster #

Sowohl subplotsals subplot_mosaicauch lassen zu, dass die Zeilen im Raster unterschiedliche Höhen und die Spalten unterschiedliche Breiten haben, indem das Schlüsselwortargument gridspec_kw verwendet wird . Von akzeptierte Abstandsparameter GridSpec können an subplotsund übergeben werden 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()')
plt.subplot_mosaic()
Text(0.5, 0.9880942857142857, 'plt.subplot_mosaic()')

Layouts für verschachtelte Achsen #

Manchmal ist es hilfreich, zwei oder mehr Achsenraster zu haben, die möglicherweise nicht miteinander in Beziehung stehen müssen. Der einfachste Weg, dies zu erreichen, ist die Verwendung von Figure.subfigures. Beachten Sie, dass die Unterfiguren-Layouts unabhängig sind, sodass die Axes-Stacheln in jeder Unterfigur nicht unbedingt ausgerichtet sind. Unten finden Sie eine ausführlichere Methode, um denselben Effekt mit zu erzielen 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]')
Achsen anordnen
Text(0.016867713730569944, 0.5, 'ylabel for subfigs[1]')

Es ist auch möglich, Achsen mithilfe subplot_mosaicvon verschachtelten Listen zu verschachteln. suptitleDiese Methode verwendet keine Unterfiguren wie oben, daher fehlt die Möglichkeit, pro Unterfigur und supxlabelusw. hinzuzufügen . Vielmehr ist es ein praktischer Wrapper um die subgridspec unten beschriebene Methode.

inner = [['innerA'],
         ['innerB']]
outer = [['upper left',  inner],
          ['lower left', 'lower right']]

fig, axd = plt.subplot_mosaic(outer, layout="constrained")
for k in axd:
    annotate_axes(axd[k], f'axd["{k}"]')
Achsen anordnen

Low-Level- und Advanced-Grid-Methoden #

Intern wird die Anordnung eines Axes-Rasters gesteuert, indem Instanzen von GridSpecund erstellt werden SubplotSpec. GridSpec definiert ein (möglicherweise uneinheitliches) Gitter aus Zellen. Die Indexierung in die GridSpec gibt eine SubplotSpec zurück, die eine oder mehrere Gitterzellen abdeckt und verwendet werden kann, um die Position einer Achse anzugeben.

Die folgenden Beispiele zeigen, wie Low-Level-Methoden verwendet werden, um Axes mithilfe von GridSpec - Objekten anzuordnen.

Einfaches 2x2-Raster #

Wir können ein 2x2-Raster auf die gleiche Weise erstellen wie :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')
Manuell hinzugefügte Subplots mit add_gridspec
Text(0.5, 0.9880942857142857, 'Manually added subplots using add_gridspec')

Achsen, die Zeilen oder Gitter in einem Gitter überspannen #

Wir können das Spezifikations -Array mit der NumPy-Slice-Syntax indizieren, und die neuen Axes überspannen das Slice. Dies wäre dasselbe wie :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')
Manuell hinzugefügte Subplots, die sich über eine Spalte erstrecken
Text(0.5, 0.9880942857142857, 'Manually added subplots, spanning a column')

Manuelle Anpassungen an ein GridSpec- Layout #

Wenn explizit eine GridSpec verwendet wird, können Sie die Layoutparameter von Subplots anpassen, die aus der GridSpec erstellt werden . Beachten Sie, dass diese Option nicht mit constrained_layoutoder kompatibel ist, die sowohl links als auch rechtsFigure.tight_layout ignorieren und die Größe der Teilplots anpassen, um die Figur auszufüllen. Normalerweise erfordert eine solche manuelle Platzierung Iterationen, damit die Tick-Beschriftungen der Achsen die Achsen nicht überlappen.

Diese Abstandsparameter können auch an subplotsund subplot_mosaicals Argument gridspec_kw übergeben werden .

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')
Manuelle Gridspec mit right=0.75
Text(0.5, 0.98, 'Manual gridspec with right=0.75')

Verschachtelte Layouts mit SubplotSpec #

Sie können ein verschachteltes Layout ähnlich wie subfiguresmit erstellen subgridspec. Hier sind die Stacheln der Achsen ausgerichtet.

Beachten Sie, dass dies auch über die ausführlichere verfügbar ist 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')
verschachtelte Gitterspezifikationen
Text(0.5, 0.99131875, 'nested gridspecs')

Hier ist ein anspruchsvolleres Beispiel für verschachtelte GridSpec : Wir erstellen ein äußeres 4x4-Raster, wobei jede Zelle ein inneres 3x3-Raster aus Achsen enthält. Wir skizzieren das äußere 4x4-Gitter, indem wir die entsprechenden Stacheln in jedem der inneren 3x3-Gitter verstecken.

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()
Achsen anordnen

Mehr lesen #

Gesamtlaufzeit des Skripts: ( 0 Minuten 13.006 Sekunden)

Galerie generiert von Sphinx-Gallery