Constrained layout guide#

Verwenden Sie Constrained layout, um Plots sauber in Ihre Abbildung einzupassen.

Constrained layout passt Subplots automatisch an, sodass Dekorationen wie Achsenbeschriftungen, Legenden und Farbleisten nicht überlappen, während die vom Benutzer angeforderte logische Anordnung beibehalten wird.

Constrained layout ist ähnlich wie Tight layout, aber wesentlich flexibler. Es behandelt Farbleisten, die auf mehreren Achsen platziert sind (Platzieren von Farbleisten), verschachtelte Layouts (subfigures) und Achsen, die sich über Zeilen oder Spalten erstrecken (subplot_mosaic), und versucht, Achsen derselben Zeile oder Spalte auszurichten. Zusätzlich versucht Compressed layout, Achsen mit festem Seitenverhältnis näher zusammenzuschieben. Diese Funktionen werden in diesem Dokument beschrieben, ebenso wie einige Implementierungsdetails am Ende.

Constrained layout muss in der Regel aktiviert werden, bevor Achsen zu einer Abbildung hinzugefügt werden. Zwei Möglichkeiten, dies zu tun, sind

Diese werden in den folgenden Abschnitten detailliert beschrieben.

Warnung

Aufruf von tight_layout schaltet constrained layout aus!

Einfaches Beispiel#

Bei der Standard-Achsenpositionierung können Achsentitel, Achsenbeschriftungen oder Tick-Beschriftungen manchmal außerhalb des Abbildungsbereichs liegen und werden daher abgeschnitten.

import matplotlib.pyplot as plt
import numpy as np

import matplotlib.colors as mcolors
import matplotlib.gridspec as gridspec

plt.rcParams['savefig.facecolor'] = "0.8"
plt.rcParams['figure.figsize'] = 4.5, 4.
plt.rcParams['figure.max_open_warning'] = 50


def example_plot(ax, fontsize=12, hide_labels=False):
    ax.plot([1, 2])

    ax.locator_params(nbins=3)
    if hide_labels:
        ax.set_xticklabels([])
        ax.set_yticklabels([])
    else:
        ax.set_xlabel('x-label', fontsize=fontsize)
        ax.set_ylabel('y-label', fontsize=fontsize)
        ax.set_title('Title', fontsize=fontsize)

fig, ax = plt.subplots(layout=None)
example_plot(ax, fontsize=24)
Title

Um dies zu verhindern, muss die Position der Achsen angepasst werden. Für Subplots kann dies manuell durch Anpassen der Subplot-Parameter mit Figure.subplots_adjust erfolgen. Die Angabe Ihrer Abbildung mit dem Schlüsselwortargument layout="constrained" nimmt die Anpassung jedoch automatisch vor.

fig, ax = plt.subplots(layout="constrained")
example_plot(ax, fontsize=24)
Title

Wenn Sie mehrere Subplots haben, überlappen sich oft die Beschriftungen verschiedener Achsen.

fig, axs = plt.subplots(2, 2, layout=None)
for ax in axs.flat:
    example_plot(ax)
Title, Title, Title, Title

Die Angabe von layout="constrained" im Aufruf von plt.subplots sorgt dafür, dass das Layout korrekt eingeschränkt wird.

fig, axs = plt.subplots(2, 2, layout="constrained")
for ax in axs.flat:
    example_plot(ax)
Title, Title, Title, Title

Farbleisten#

Wenn Sie eine Farbleiste mit Figure.colorbar erstellen, müssen Sie Platz dafür schaffen. Constrained layout erledigt dies automatisch. Beachten Sie, dass use_gridspec=True ignoriert wird, da diese Option zur Verbesserung des Layouts über tight_layout dient.

Hinweis

Für die Schlüsselwortargumente von pcolormesh (pc_kwargs) verwenden wir ein Dictionary, um die Aufrufe in diesem Dokument konsistent zu halten.

arr = np.arange(100).reshape((10, 10))
norm = mcolors.Normalize(vmin=0., vmax=100.)
# see note above: this makes all pcolormesh calls consistent:
pc_kwargs = {'rasterized': True, 'cmap': 'viridis', 'norm': norm}
fig, ax = plt.subplots(figsize=(4, 4), layout="constrained")
im = ax.pcolormesh(arr, **pc_kwargs)
fig.colorbar(im, ax=ax, shrink=0.6)
constrainedlayout guide

Wenn Sie eine Liste von Achsen (oder einen anderen iterierbaren Container) für das Argument ax von colorbar angeben, nimmt constrained layout Platz von den angegebenen Achsen.

fig, axs = plt.subplots(2, 2, figsize=(4, 4), layout="constrained")
for ax in axs.flat:
    im = ax.pcolormesh(arr, **pc_kwargs)
fig.colorbar(im, ax=axs, shrink=0.6)
constrainedlayout guide

Wenn Sie eine Liste von Achsen aus einem Gitter von Achsen angeben, wird die Farbleiste entsprechend Platz stehlen und eine Lücke hinterlassen, aber alle Subplots bleiben gleich groß.

fig, axs = plt.subplots(3, 3, figsize=(4, 4), layout="constrained")
for ax in axs.flat:
    im = ax.pcolormesh(arr, **pc_kwargs)
fig.colorbar(im, ax=axs[1:, 1], shrink=0.8)
fig.colorbar(im, ax=axs[:, -1], shrink=0.6)
constrainedlayout guide

Suptitle#

Constrained layout kann auch Platz für suptitle schaffen.

fig, axs = plt.subplots(2, 2, figsize=(4, 4), layout="constrained")
for ax in axs.flat:
    im = ax.pcolormesh(arr, **pc_kwargs)
fig.colorbar(im, ax=axs, shrink=0.6)
fig.suptitle('Big Suptitle')
Big Suptitle

Legenden#

Legenden können außerhalb ihrer übergeordneten Achse platziert werden. Constrained layout ist dafür bei Axes.legend() konzipiert. Constrained layout unterstützt jedoch (noch) keine Legenden, die über Figure.legend() erstellt werden.

fig, ax = plt.subplots(layout="constrained")
ax.plot(np.arange(10), label='This is a plot')
ax.legend(loc='center left', bbox_to_anchor=(0.8, 0.5))
constrainedlayout guide

Dies wird jedoch Platz vom Subplot-Layout stehlen

fig, axs = plt.subplots(1, 2, figsize=(4, 2), layout="constrained")
axs[0].plot(np.arange(10))
axs[1].plot(np.arange(10), label='This is a plot')
axs[1].legend(loc='center left', bbox_to_anchor=(0.8, 0.5))
constrainedlayout guide

Damit eine Legende oder ein anderer Künstler keinen Platz vom Subplot-Layout stehlen kann, können wir leg.set_in_layout(False) verwenden. Dies kann natürlich dazu führen, dass die Legende abgeschnitten wird, kann aber nützlich sein, wenn der Plot anschließend mit fig.savefig('outname.png', bbox_inches='tight') aufgerufen wird. Beachten Sie jedoch, dass der get_in_layout-Status der Legende erneut umgeschaltet werden muss, damit die gespeicherte Datei funktioniert, und wir ein manuelles Zeichnen auslösen müssen, wenn wir möchten, dass constrained layout die Größe der Achsen vor dem Drucken anpasst.

fig, axs = plt.subplots(1, 2, figsize=(4, 2), layout="constrained")

axs[0].plot(np.arange(10))
axs[1].plot(np.arange(10), label='This is a plot')
leg = axs[1].legend(loc='center left', bbox_to_anchor=(0.8, 0.5))
leg.set_in_layout(False)
# trigger a draw so that constrained layout is executed once
# before we turn it off when printing....
fig.canvas.draw()
# we want the legend included in the bbox_inches='tight' calcs.
leg.set_in_layout(True)
# we don't want the layout to change at this point.
fig.set_layout_engine('none')
try:
    fig.savefig('../../../doc/_static/constrained_layout_1b.png',
                bbox_inches='tight', dpi=100)
except FileNotFoundError:
    # this allows the script to keep going if run interactively and
    # the directory above doesn't exist
    pass
constrainedlayout guide

Die gespeicherte Datei sieht so aus

../../../_images/constrained_layout_1b.png

Ein besserer Weg, diese Unannehmlichkeiten zu umgehen, ist die einfache Verwendung der von Figure.legend bereitgestellten Legendenmethode.

fig, axs = plt.subplots(1, 2, figsize=(4, 2), layout="constrained")
axs[0].plot(np.arange(10))
lines = axs[1].plot(np.arange(10), label='This is a plot')
labels = [l.get_label() for l in lines]
leg = fig.legend(lines, labels, loc='center left',
                 bbox_to_anchor=(0.8, 0.5), bbox_transform=axs[1].transAxes)
try:
    fig.savefig('../../../doc/_static/constrained_layout_2b.png',
                bbox_inches='tight', dpi=100)
except FileNotFoundError:
    # this allows the script to keep going if run interactively and
    # the directory above doesn't exist
    pass
constrainedlayout guide

Die gespeicherte Datei sieht so aus

../../../_images/constrained_layout_2b.png

Abstand und Leerraum#

Der Abstand zwischen den Achsen wird horizontal durch w_pad und wspace und vertikal durch h_pad und hspace gesteuert. Diese können über set bearbeitet werden. w/h_pad sind die Mindestabstände um die Achsen in Zoll.

fig, axs = plt.subplots(2, 2, layout="constrained")
for ax in axs.flat:
    example_plot(ax, hide_labels=True)
fig.get_layout_engine().set(w_pad=4 / 72, h_pad=4 / 72, hspace=0,
                            wspace=0)
constrainedlayout guide

Der Abstand zwischen den Subplots wird weiter durch wspace und hspace festgelegt. Diese werden als Bruchteil der Gesamtgröße der Subplot-Gruppe angegeben. Wenn diese Werte kleiner sind als w_pad oder h_pad, werden die festen Pads verwendet. Beachten Sie im Folgenden, wie sich der Abstand an den Rändern nicht vom obigen ändert, aber der Abstand zwischen den Subplots schon.

fig, axs = plt.subplots(2, 2, layout="constrained")
for ax in axs.flat:
    example_plot(ax, hide_labels=True)
fig.get_layout_engine().set(w_pad=4 / 72, h_pad=4 / 72, hspace=0.2,
                            wspace=0.2)
constrainedlayout guide

Wenn es mehr als zwei Spalten gibt, wird der wspace zwischen ihnen geteilt, sodass hier der wspace in zwei Teile geteilt wird, mit einem wspace von 0,1 zwischen jeder Spalte.

fig, axs = plt.subplots(2, 3, layout="constrained")
for ax in axs.flat:
    example_plot(ax, hide_labels=True)
fig.get_layout_engine().set(w_pad=4 / 72, h_pad=4 / 72, hspace=0.2,
                            wspace=0.2)
constrainedlayout guide

GridSpecs haben auch optionale Schlüsselwortargumente hspace und wspace, die anstelle der von constrained layout gesetzten Pads verwendet werden.

fig, axs = plt.subplots(2, 2, layout="constrained",
                        gridspec_kw={'wspace': 0.3, 'hspace': 0.2})
for ax in axs.flat:
    example_plot(ax, hide_labels=True)
# this has no effect because the space set in the gridspec trumps the
# space set in *constrained layout*.
fig.get_layout_engine().set(w_pad=4 / 72, h_pad=4 / 72, hspace=0.0,
                            wspace=0.0)
constrainedlayout guide

Abstand mit Farbleisten#

Farbleisten werden im Abstand pad von ihrem Elternteil platziert, wobei pad ein Bruchteil der Breite des/der Elternteile(s) ist. Der Abstand zum nächsten Subplot ergibt sich dann aus w/hspace.

fig, axs = plt.subplots(2, 2, layout="constrained")
pads = [0, 0.05, 0.1, 0.2]
for pad, ax in zip(pads, axs.flat):
    pc = ax.pcolormesh(arr, **pc_kwargs)
    fig.colorbar(pc, ax=ax, shrink=0.6, pad=pad)
    ax.set_xticklabels([])
    ax.set_yticklabels([])
    ax.set_title(f'pad: {pad}')
fig.get_layout_engine().set(w_pad=2 / 72, h_pad=2 / 72, hspace=0.2,
                            wspace=0.2)
pad: 0, pad: 0.05, pad: 0.1, pad: 0.2

rcParams#

Es gibt fünf rcParams, die entweder in einem Skript oder in der Datei matplotlibrc gesetzt werden können. Sie alle haben das Präfix figure.constrained_layout.

  • use: Ob constrained layout verwendet werden soll. Standard ist False.

  • w_pad, h_pad: Abstand um Achsenobjekte. Float, der Zoll darstellt. Standard ist 3./72. Zoll (3 pts).

  • wspace, hspace: Abstand zwischen Subplot-Gruppen. Float, der einen Bruchteil der zu trennenden Subplot-Breiten darstellt. Standard ist 0,02.

plt.rcParams['figure.constrained_layout.use'] = True
fig, axs = plt.subplots(2, 2, figsize=(3, 3))
for ax in axs.flat:
    example_plot(ax)
Title, Title, Title, Title

Verwendung mit GridSpec#

Constrained layout ist für die Verwendung mit subplots(), subplot_mosaic() oder GridSpec() mit add_subplot() vorgesehen.

Beachten Sie, dass im Folgenden layout="constrained" verwendet wird.

plt.rcParams['figure.constrained_layout.use'] = False
fig = plt.figure(layout="constrained")

gs1 = gridspec.GridSpec(2, 1, figure=fig)
ax1 = fig.add_subplot(gs1[0])
ax2 = fig.add_subplot(gs1[1])

example_plot(ax1)
example_plot(ax2)
Title, Title

Komplexere GridSpec-Layouts sind möglich. Beachten Sie, dass wir hier die Komfortfunktionen add_gridspec und subgridspec verwenden.

fig = plt.figure(layout="constrained")

gs0 = fig.add_gridspec(1, 2)

gs1 = gs0[0].subgridspec(2, 1)
ax1 = fig.add_subplot(gs1[0])
ax2 = fig.add_subplot(gs1[1])

example_plot(ax1)
example_plot(ax2)

gs2 = gs0[1].subgridspec(3, 1)

for ss in gs2:
    ax = fig.add_subplot(ss)
    example_plot(ax)
    ax.set_title("")
    ax.set_xlabel("")

ax.set_xlabel("x-label", fontsize=12)
Title, Title

Beachten Sie, dass in der obigen Abbildung die linke und rechte Spalte nicht die gleiche vertikale Ausdehnung haben. Wenn wir möchten, dass sich die Ober- und Unterseite der beiden Gitter ausrichten, müssen sie im selben Gridspec liegen. Wir müssen diese Abbildung auch größer machen, damit die Achsen nicht auf Höhe Null kollabieren.

fig = plt.figure(figsize=(4, 6), layout="constrained")

gs0 = fig.add_gridspec(6, 2)

ax1 = fig.add_subplot(gs0[:3, 0])
ax2 = fig.add_subplot(gs0[3:, 0])

example_plot(ax1)
example_plot(ax2)

ax = fig.add_subplot(gs0[0:2, 1])
example_plot(ax, hide_labels=True)
ax = fig.add_subplot(gs0[2:4, 1])
example_plot(ax, hide_labels=True)
ax = fig.add_subplot(gs0[4:, 1])
example_plot(ax, hide_labels=True)
fig.suptitle('Overlapping Gridspecs')
Overlapping Gridspecs, Title, Title

Dieses Beispiel verwendet zwei GridSpecs, damit die Farbleiste nur für einen Satz von Pcolors gilt. Beachten Sie, wie die linke Spalte aufgrund dessen breiter ist als die beiden rechten Spalten. Wenn Sie möchten, dass die Subplots die gleiche Größe haben, benötigen Sie natürlich nur einen Gridspec. Beachten Sie, dass der gleiche Effekt mit subfigures erzielt werden kann.

fig = plt.figure(layout="constrained")
gs0 = fig.add_gridspec(1, 2, figure=fig, width_ratios=[1, 2])
gs_left = gs0[0].subgridspec(2, 1)
gs_right = gs0[1].subgridspec(2, 2)

for gs in gs_left:
    ax = fig.add_subplot(gs)
    example_plot(ax)
axs = []
for gs in gs_right:
    ax = fig.add_subplot(gs)
    pcm = ax.pcolormesh(arr, **pc_kwargs)
    ax.set_xlabel('x-label')
    ax.set_ylabel('y-label')
    ax.set_title('title')
    axs += [ax]
fig.suptitle('Nested plots using subgridspec')
fig.colorbar(pcm, ax=axs)
Nested plots using subgridspec, Title, Title, title, title, title, title

Anstatt Subgridspecs zu verwenden, bietet Matplotlib nun subfigures an, die ebenfalls mit constrained layout funktionieren.

fig = plt.figure(layout="constrained")
sfigs = fig.subfigures(1, 2, width_ratios=[1, 2])

axs_left = sfigs[0].subplots(2, 1)
for ax in axs_left.flat:
    example_plot(ax)

axs_right = sfigs[1].subplots(2, 2)
for ax in axs_right.flat:
    pcm = ax.pcolormesh(arr, **pc_kwargs)
    ax.set_xlabel('x-label')
    ax.set_ylabel('y-label')
    ax.set_title('title')
fig.colorbar(pcm, ax=axs_right)
fig.suptitle('Nested plots using subfigures')
Nested plots using subfigures, Title, Title, title, title, title, title

Manuelles Festlegen von Achsenpositionen#

Es kann gute Gründe geben, eine Achsenposition manuell festzulegen. Ein manueller Aufruf von set_position setzt die Achsen so, dass constrained layout keine Wirkung mehr darauf hat. (Beachten Sie, dass constrained layout den Platz für die verschobene Achse weiterhin lässt).

fig, axs = plt.subplots(1, 2, layout="constrained")
example_plot(axs[0], fontsize=12)
axs[1].set_position([0.2, 0.2, 0.4, 0.4])
Title

Gitter von Achsen mit festem Seitenverhältnis: "komprimiertes" Layout#

Constrained layout arbeitet auf dem Gitter der "ursprünglichen" Positionen für Achsen. Wenn Achsen jedoch ein festes Seitenverhältnis haben, wird eine Seite normalerweise kürzer gemacht, was große Lücken in der verkürzten Richtung hinterlässt. Im Folgenden sind die Achsen quadratisch, aber die Abbildung ist recht breit, sodass eine horizontale Lücke entsteht.

fig, axs = plt.subplots(2, 2, figsize=(5, 3),
                        sharex=True, sharey=True, layout="constrained")
for ax in axs.flat:
    ax.imshow(arr)
fig.suptitle("fixed-aspect plots, layout='constrained'")
fixed-aspect plots, layout='constrained'

Eine offensichtliche Möglichkeit, dies zu beheben, besteht darin, die Abbildungsgröße quadratischer zu machen, das exakte Schließen der Lücken erfordert jedoch Versuch und Irrtum. Für einfache Achsen-Gitter können wir layout="compressed" verwenden, um dies für uns zu erledigen.

fig, axs = plt.subplots(2, 2, figsize=(5, 3),
                        sharex=True, sharey=True, layout='compressed')
for ax in axs.flat:
    ax.imshow(arr)
fig.suptitle("fixed-aspect plots, layout='compressed'")
fixed-aspect plots, layout='compressed'

Manuelles Deaktivieren von constrained layout#

Constrained layout passt die Achsenpositionen normalerweise bei jeder Zeichnung der Abbildung an. Wenn Sie den von constrained layout bereitgestellten Abstand erhalten möchten, aber nicht möchten, dass er aktualisiert wird, führen Sie die anfängliche Zeichnung durch und rufen Sie dann fig.set_layout_engine('none') auf. Dies kann für Animationen nützlich sein, bei denen sich die Länge der Tick-Beschriftungen ändern kann.

Beachten Sie, dass constrained layout für GUI-Ereignisse ZOOM und PAN für Backends, die die Symbolleiste verwenden, deaktiviert ist. Dies verhindert, dass sich die Achsen während des Zooms und Verschiebens ändern.

Einschränkungen#

Inkompatible Funktionen#

Constrained layout funktioniert mit pyplot.subplot, aber nur, wenn die Anzahl der Zeilen und Spalten für jeden Aufruf gleich ist. Der Grund dafür ist, dass jeder Aufruf von pyplot.subplot eine neue GridSpec-Instanz erstellt, wenn die Geometrie nicht gleich ist, und constrained layout. Daher funktioniert das Folgende einwandfrei.

fig = plt.figure(layout="constrained")

ax1 = plt.subplot(2, 2, 1)
ax2 = plt.subplot(2, 2, 3)
# third Axes that spans both rows in second column:
ax3 = plt.subplot(2, 2, (2, 4))

example_plot(ax1)
example_plot(ax2)
example_plot(ax3)
plt.suptitle('Homogeneous nrows, ncols')
Homogeneous nrows, ncols, Title, Title, Title

aber das Folgende führt zu einem schlechten Layout.

fig = plt.figure(layout="constrained")

ax1 = plt.subplot(2, 2, 1)
ax2 = plt.subplot(2, 2, 3)
ax3 = plt.subplot(1, 2, 2)

example_plot(ax1)
example_plot(ax2)
example_plot(ax3)
plt.suptitle('Mixed nrows, ncols')
Mixed nrows, ncols, Title, Title, Title

Ähnlich funktioniert subplot2grid mit derselben Einschränkung, dass nrows und ncols nicht geändert werden dürfen, damit das Layout gut aussieht.

fig = plt.figure(layout="constrained")

ax1 = plt.subplot2grid((3, 3), (0, 0))
ax2 = plt.subplot2grid((3, 3), (0, 1), colspan=2)
ax3 = plt.subplot2grid((3, 3), (1, 0), colspan=2, rowspan=2)
ax4 = plt.subplot2grid((3, 3), (1, 2), rowspan=2)

example_plot(ax1)
example_plot(ax2)
example_plot(ax3)
example_plot(ax4)
fig.suptitle('subplot2grid')
subplot2grid, Title, Title, Title, Title

Weitere Hinweise#

  • Constrained layout berücksichtigt nur Tick-Beschriftungen, Achsenbeschriftungen, Titel und Legenden. Andere Künstler können daher abgeschnitten werden und sich auch überlappen.

  • Es wird davon ausgegangen, dass der zusätzliche Platz, der für Tick-Beschriftungen, Achsenbeschriftungen und Titel benötigt wird, unabhängig von der ursprünglichen Position der Achsen ist. Dies ist oft der Fall, aber es gibt seltene Fälle, in denen dies nicht so ist.

  • Es gibt geringfügige Unterschiede in der Art und Weise, wie die Backends Schriftarten rendern, sodass die Ergebnisse nicht Pixel für Pixel identisch sind.

  • Ein Künstler, der Koordinaten verwendet, die über die Achsengrenze hinausgehen, führt zu ungewöhnlichen Layouts, wenn er zu einer Achse hinzugefügt wird. Dies kann vermieden werden, indem der Künstler direkt zur Figure über add_artist() hinzugefügt wird. Siehe ConnectionPatch für ein Beispiel.

Fehlersuche#

Constrained layout kann auf etwas unerwartete Weise fehlschlagen. Da es einen Constraint-Solver verwendet, kann der Solver mathematisch korrekte Lösungen finden, die aber nicht dem entsprechen, was der Benutzer möchte. Der übliche Fehlerfall ist, dass alle Größen auf ihren kleinstmöglichen Wert kollabieren. Wenn dies geschieht, liegt es an einem von zwei Gründen:

  1. Es war nicht genügend Platz für die Elemente vorhanden, die Sie zeichnen wollten.

  2. Es gibt einen Fehler – in diesem Fall öffnen Sie ein Problem unter matplotlib/matplotlib#issues.

Wenn es einen Fehler gibt, melden Sie ihn bitte mit einem in sich geschlossenen Beispiel, das keine externen Daten oder Abhängigkeiten (außer numpy) benötigt.

Hinweise zum Algorithmus#

Der Algorithmus für die Einschränkung ist relativ einfach, weist jedoch aufgrund der komplexen Möglichkeiten, eine Abbildung anzuordnen, einige Komplexitäten auf.

Das Layout in Matplotlib wird mit GridSpecs über die Klasse GridSpec realisiert. Ein GridSpec ist eine logische Unterteilung der Abbildung in Zeilen und Spalten, wobei die relative Breite der Achsen in diesen Zeilen und Spalten durch width_ratios und height_ratios festgelegt wird.

Bei constrained layout erhält jedes GridSpec ein zugeordnetes layoutgrid. Das layoutgrid hat eine Reihe von left und right Variablen für jede Spalte und bottom und top Variablen für jede Zeile, und zusätzlich einen Rand für jede der linken, rechten, unteren und oberen Seiten. In jeder Zeile werden die unteren/oberen Ränder verbreitert, bis alle Dekorationen in dieser Zeile untergebracht sind. Ebenso für Spalten und die linken/rechten Ränder.

Einfacher Fall: eine Achse#

Für eine einzelne Achse ist das Layout unkompliziert. Es gibt ein übergeordnetes Layout-Gitter für die Abbildung, das aus einer Spalte und einer Zeile besteht, und ein untergeordnetes Layout-Gitter für das GridSpec, das die Achse enthält, ebenfalls aus einer Zeile und einer Spalte bestehend. Platz wird für die "Dekorationen" an jeder Seite der Achse geschaffen. Im Code wird dies durch die Einträge in do_constrained_layout() erreicht, wie z.B.

gridspec._layoutgrid[0, 0].edit_margin_min('left',
      -bbox.x0 + pos.x0 + w_pad)

wobei bbox die enge Bounding Box der Achse ist und pos deren Position. Beachten Sie, wie die vier Ränder die Achsendekorationen umfassen.

from matplotlib._layoutgrid import plot_children

fig, ax = plt.subplots(layout="constrained")
example_plot(ax, fontsize=24)
plot_children(fig)
Title

Einfacher Fall: zwei Achsen#

Wenn es mehrere Achsen gibt, sind deren Layouts auf einfache Weise verbunden. In diesem Beispiel hat die linke Achse deutlich größere Dekorationen als die rechte, aber sie teilen sich einen unteren Rand, der groß genug gemacht wird, um die größere X-Achsenbeschriftung aufzunehmen. Dasselbe gilt für den gemeinsamen oberen Rand. Die linken und rechten Ränder werden nicht geteilt und dürfen daher unterschiedlich sein.

fig, ax = plt.subplots(1, 2, layout="constrained")
example_plot(ax[0], fontsize=32)
example_plot(ax[1], fontsize=8)
plot_children(fig)
Title, Title

Zwei Achsen und Farbleiste#

Eine Farbleiste ist einfach ein weiteres Element, das den Rand der übergeordneten Layout-Gitterzelle erweitert.

fig, ax = plt.subplots(1, 2, layout="constrained")
im = ax[0].pcolormesh(arr, **pc_kwargs)
fig.colorbar(im, ax=ax[0], shrink=0.6)
im = ax[1].pcolormesh(arr, **pc_kwargs)
plot_children(fig)
constrainedlayout guide

Farbleiste, die einem Gridspec zugeordnet ist#

Wenn eine Farbleiste zu mehr als einer Zelle des Gitters gehört, erweitert sie den Rand für jede einzelne.

fig, axs = plt.subplots(2, 2, layout="constrained")
for ax in axs.flat:
    im = ax.pcolormesh(arr, **pc_kwargs)
fig.colorbar(im, ax=axs, shrink=0.6)
plot_children(fig)
constrainedlayout guide

Ungleichmäßige Achsengrößen#

Es gibt zwei Möglichkeiten, Achsen in einem Gridspec-Layout ungleichmäßig groß zu machen: entweder durch Angabe, dass sie Gridspec-Zeilen oder -Spalten überspannen sollen, oder durch Angabe von Breiten- und Höhenverhältnissen.

Die erste Methode wird hier verwendet. Beachten Sie, dass die mittleren top- und bottom-Ränder nicht von der linken Spalte beeinflusst werden. Dies ist eine bewusste Entscheidung des Algorithmus und führt dazu, dass die beiden rechten Achsen die gleiche Höhe haben, aber diese nicht 1/2 der Höhe der linken Achse beträgt. Dies entspricht der Funktionsweise von gridspec ohne constrained layout.

fig = plt.figure(layout="constrained")
gs = gridspec.GridSpec(2, 2, figure=fig)
ax = fig.add_subplot(gs[:, 0])
im = ax.pcolormesh(arr, **pc_kwargs)
ax = fig.add_subplot(gs[0, 1])
im = ax.pcolormesh(arr, **pc_kwargs)
ax = fig.add_subplot(gs[1, 1])
im = ax.pcolormesh(arr, **pc_kwargs)
plot_children(fig)
constrainedlayout guide

Ein Fall, der Feinabstimmung erfordert, ist, wenn Ränder keine Künstler haben, die ihre Breite einschränken. Im folgenden Fall haben der rechte Rand von Spalte 0 und der linke Rand von Spalte 3 keine Randkünstler, die ihre Breite festlegen. Daher nehmen wir die maximale Breite der Ränder, die Künstler haben. Dies führt dazu, dass alle Achsen die gleiche Größe haben.

fig = plt.figure(layout="constrained")
gs = fig.add_gridspec(2, 4)
ax00 = fig.add_subplot(gs[0, 0:2])
ax01 = fig.add_subplot(gs[0, 2:])
ax10 = fig.add_subplot(gs[1, 1:3])
example_plot(ax10, fontsize=14)
plot_children(fig)
plt.show()
Title

Gesamtlaufzeit des Skripts: (0 Minuten 22,366 Sekunden)

Galerie generiert von Sphinx-Gallery