Leitfaden für eingeschränktes Layout #

So verwenden Sie eingeschränktes Layout, um Diagramme sauber in Ihre Figur einzupassen.

constrained_layout passt Subplots und Dekorationen wie Legenden und Farbbalken automatisch so an, dass sie in das Figurenfenster passen, während das vom Benutzer gewünschte logische Layout so gut wie möglich erhalten bleibt.

constrained_layout ähnelt tight_layout , verwendet jedoch einen Constraint-Solver, um die Größe der Achsen zu bestimmen, die es ihnen ermöglicht, zu passen.

constrained_layout muss normalerweise aktiviert werden, bevor einer Figur Achsen hinzugefügt werden. Dazu gibt es zwei Möglichkeiten

Diese werden in den folgenden Abschnitten ausführlich beschrieben.

Einfaches Beispiel #

In Matplotlib wird die Position von Achsen (einschließlich Subplots) in normalisierten Figurenkoordinaten angegeben. Es kann vorkommen, dass Ihre Achsenbeschriftungen oder -titel (oder manchmal sogar Teilstrichbeschriftungen) außerhalb des Abbildungsbereichs liegen und daher abgeschnitten werden.

import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import matplotlib.gridspec as gridspec
import numpy as np

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

Um dies zu verhindern, muss die Position der Achsen angepasst werden. Bei Nebenhandlungen kann dies manuell erfolgen, indem Sie die Nebenhandlungsparameter mit anpassen Figure.subplots_adjust. Wenn Sie Ihre Zahl jedoch mit dem layout="constrained"Schlüsselwortargument # angeben, wird die Anpassung # automatisch durchgeführt.

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

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

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

Die Angabe layout="constrained"im Aufruf von plt.subplots bewirkt, dass das Layout ordnungsgemäß eingeschränkt wird.

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

Farbbalken #

Wenn Sie einen Farbbalken mit erstellen Figure.colorbar, müssen Sie Platz dafür schaffen. constrained_layoutmacht das automatisch. Beachten Sie, dass die Angabe use_gridspec=Trueignoriert wird, da diese Option zur Verbesserung des Layouts über verwendet wird tight_layout.

Notiz

Für die pcolormeshSchlüsselwortargumente ( pc_kwargs) verwenden wir ein Wörterbuch. Im Folgenden weisen wir einer Reihe von Achsen einen Farbbalken zu, die jeweils ein ScalarMappable; Durch die Angabe der Norm und der Farbtabelle wird sichergestellt, dass der Farbbalken für alle Achsen genau ist.

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)
Leitfaden für eingeschränkte Layouts
<matplotlib.colorbar.Colorbar object at 0x7f2cfafb53c0>

Wenn Sie eine Liste von Achsen (oder einen anderen iterierbaren Container) für das axArgument von colorbarangeben, nimmt constrained_layout Platz von den angegebenen Achsen ein.

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)
Leitfaden für eingeschränkte Layouts
<matplotlib.colorbar.Colorbar object at 0x7f2cfb6eed70>

Wenn Sie eine Liste von Achsen innerhalb eines Achsenrasters angeben, nimmt der Farbbalken angemessen Platz ein und hinterlässt eine Lücke, aber alle Unterdiagramme haben immer noch dieselbe Größe.

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)
Leitfaden für eingeschränkte Layouts
<matplotlib.colorbar.Colorbar object at 0x7f2cdd1a3340>

Untertitel #

constrained_layoutkann auch Platz schaffen suptitle.

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')
Großer Untertitel
Text(0.5, 0.9895825, 'Big Suptitle')

Legenden #

Legenden können außerhalb ihrer übergeordneten Achse platziert werden. Das eingeschränkte Layout wurde entwickelt, um dies für Axes.legend(). Das eingeschränkte Layout verarbeitet jedoch (noch) keine Legenden, die über erstellt wurden .Figure.legend()

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))
Leitfaden für eingeschränkte Layouts
<matplotlib.legend.Legend object at 0x7f2cfb266d70>

Dies wird jedoch Platz von einem Nebenplot-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))
Leitfaden für eingeschränkte Layouts
<matplotlib.legend.Legend object at 0x7f2cf99852a0>

Damit eine Legende oder ein anderer Künstler keinen Platz aus dem Layout der Nebenhandlung stiehlt, können wir leg.set_in_layout(False). Das kann natürlich dazu führen, dass die Legende abgeschnitten wird, kann aber nützlich sein, wenn die Handlung nachträglich mit aufgerufen wird . Beachten Sie jedoch, dass der Status der Legende erneut umgeschaltet werden muss, damit die gespeicherte Datei funktioniert, und wir müssen manuell ein Zeichnen auslösen, wenn wir möchten, dass constrained_layout die Größe der Achsen vor dem Drucken anpasst.fig.savefig('outname.png', bbox_inches='tight')get_in_layout

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
Leitfaden für eingeschränkte Layouts

Die gespeicherte Datei sieht so aus:

../../_images/constrained_layout_1b.png

Eine bessere Möglichkeit, diese Unbeholfenheit zu umgehen, besteht darin, einfach die Legendenmethode zu verwenden, die von bereitgestellt wird Figure.legend:

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
Leitfaden für eingeschränkte Layouts

Die gespeicherte Datei sieht so aus:

../../_images/constrained_layout_2b.png

Polsterung und Abstand #

Das Auffüllen zwischen den Achsen wird horizontal durch w_pad und wspace und vertikal durch h_pad und hspace gesteuert . Diese können über bearbeitet werden set. w/h_pad sind der Mindestabstand um die Achsen in Zolleinheiten:

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)
Leitfaden für eingeschränkte Layouts

Der Abstand zwischen Subplots wird weiter durch wspace und hspace festgelegt . Diese werden als Bruchteil der Größe der Unterparzellengruppe insgesamt angegeben. Wenn diese Werte kleiner als w_pad oder h_pad sind, werden stattdessen die festen Pads verwendet. Beachten Sie im Folgenden, dass sich der Abstand an den Rändern nicht von oben ändert, der Abstand zwischen den Unterplots jedoch.

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)
Leitfaden für eingeschränkte Layouts

Wenn es mehr als zwei Spalten gibt, wird der wspace zwischen ihnen geteilt, also wird der wspace hier in 2 geteilt, 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)
Leitfaden für eingeschränkte Layouts

GridSpecs haben auch optionale hspace- und wspace- Schlüsselwortargumente, die anstelle der von gesetzten Pads verwendet werden constrained_layout:

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)
Leitfaden für eingeschränkte Layouts

Abstand mit Farbbalken #

Farbbalken werden in einem Abstand Pad von ihrem übergeordneten Element platziert, wobei das Pad einen Bruchteil der Breite des übergeordneten Elements ausmacht. Der Abstand zum nächsten Subplot ist dann durch w/hspace gegeben .

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 gesetzt werden können, entweder in einem Skript oder in der matplotlibrc Datei. Sie haben alle das Präfix figure.constrained_layout:

  • use : Ob constrained_layout verwendet werden soll. Der Standardwert ist False

  • w_pad , h_pad : Padding um Achsenobjekte herum. Float, der Zoll darstellt. Standard ist 3./72. Zoll (3 Punkte)

  • wspace , hspace : Abstand zwischen Subplot-Gruppen. Gleitkommazahl, die einen Bruchteil der zu trennenden Teilflächenbreiten darstellt. Der Standardwert 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)
Titel, Titel, Titel, Titel

Mit GridSpec # verwenden

constrained_layout soll mit subplots(), subplot_mosaic()oder GridSpec()mit verwendet werden add_subplot().

Beachten Sie das im Folgendenlayout="constrained"

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)
Titel, Titel

Kompliziertere Gridspec-Layouts sind möglich. Beachten Sie, dass wir hier die Komfortfunktionen add_gridspecund verwenden subgridspec.

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)
Titel, Titel
Text(0.5, 41.33399999999999, 'x-label')

Beachten Sie, dass die linke und die rechte Spalte oben nicht die gleiche vertikale Ausdehnung haben. Wenn wir möchten, dass die Ober- und Unterseite der beiden Gitter aneinander ausgerichtet sind, müssen sie sich in derselben Gitterspezifikation befinden. Wir müssen diese Figur ebenfalls vergrößern, damit die Achsen nicht auf die Höhe Null zusammenbrechen:

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')
Überlappende Gridspecs, Titel, Titel
Text(0.5, 0.993055, 'Overlapping Gridspecs')

In diesem Beispiel werden zwei Gridspecs verwendet, damit sich der Farbbalken nur auf einen Satz von pcolors bezieht. Beachten Sie, dass die linke Spalte aus diesem Grund breiter ist als die beiden rechten Spalten. Wenn Sie wollten, dass die Subplots die gleiche Größe haben, brauchten Sie natürlich nur eine Gridspec. Beachten Sie, dass der gleiche Effekt mit erreicht werden kann subfigures.

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)
Verschachtelte Plots mit Subgridspec, Titel, Titel, Titel, Titel, Titel, Titel
<matplotlib.colorbar.Colorbar object at 0x7f2cdf471c30>

Anstatt Subgridspecs zu verwenden, stellt Matplotlib jetzt bereit subfigures , die auch mit funktionieren constrained_layout:

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')
Verschachtelte Diagramme mit Unterfiguren, Titel, Titel, Titel, Titel, Titel, Titel
Text(0.5, 0.9895825, 'Nested plots using subfigures')

Achsenpositionen manuell einstellen #

Es kann gute Gründe geben, eine Achsenposition manuell festzulegen. Ein manueller Aufruf von set_positionsetzt die Achsen so, dass constrained_layout keine Auswirkung mehr darauf hat. (Beachten Sie, dass constrained_layoutimmer noch Platz für die bewegten Achsen bleibt).

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])
Titel

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

constrained_layoutarbeitet auf dem Raster der "ursprünglichen" Positionen für Achsen. Wenn Achsen jedoch feste Seitenverhältnisse haben, wird eine Seite normalerweise kürzer gemacht und hinterlässt große Lücken in der verkürzten Richtung. Im Folgenden sind die Achsen quadratisch, aber die Figur ziemlich breit, sodass es eine horizontale Lücke gibt:

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'")
Plots mit fester Ausrichtung, layout='constrained'
Text(0.5, 0.98611, "fixed-aspect plots, layout='constrained'")

Eine offensichtliche Möglichkeit, dies zu beheben, besteht darin, die Figurengröße quadratischer zu machen, aber das genaue Schließen der Lücken erfordert Versuch und Irrtum. Für einfache Raster von Achsen können wir layout="compressed"die Arbeit für uns 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'")
Plots mit festem Seitenverhältnis, layout='komprimiert'
Text(0.5, 0.98611, "fixed-aspect plots, layout='compressed'")

Manuelles Ausschalten constrained_layout#

constrained_layoutpasst normalerweise die Achsenpositionen bei jedem Zeichnen der Figur an. Wenn Sie den von bereitgestellten Abstand erhalten möchten, ihn constrained_layoutaber nicht aktualisieren lassen möchten, führen Sie die erste Zeichnung durch und rufen Sie dann auf fig.set_layout_engine(None). Dies ist möglicherweise nützlich für Animationen, bei denen die Tick-Labels die Länge ändern können.

Beachten Sie, dass constrained_layoutfür ZOOMund PAN GUI-Ereignisse für die Backends, die die Symbolleiste verwenden, deaktiviert sind. Dadurch wird verhindert, dass sich die Achsen während des Zoomens und Schwenkens ändern.

Einschränkungen #

Inkompatible Funktionen #

constrained_layoutfunktioniert 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.subploteine neue GridSpecInstanz erstellt, wenn die Geometrie nicht dieselbe ist, und constrained_layout. Also folgendes funktioniert gut:

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('Homogenous nrows, ncols')
Homogene nrows, ncols, Titel, Titel, Titel
Text(0.5, 0.9895825, 'Homogenous nrows, ncols')

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')
Gemischte Zahlen, Ncols, Titel, Titel, Titel
Text(0.5, 0.9895825, 'Mixed nrows, ncols')

Ähnlich subplot2gridfunktioniert es mit der gleichen Einschränkung, die nrows und ncols nicht ändern können, 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, Titel, Titel, Titel, Titel
Text(0.5, 0.9895825, 'subplot2grid')

Andere Vorbehalte #

  • constrained_layoutberücksichtigt nur Ticklabels, Achsenbeschriftungen, Titel und Legenden. Somit können andere Künstler abgeschnitten werden und sich auch überlappen.

  • Es wird davon ausgegangen, dass der zusätzliche Platz, der für Teilstrichbeschriftungen, 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 der Fall ist.

  • Es gibt kleine Unterschiede in der Art und Weise, wie die Backends mit der Wiedergabe von Schriftarten umgehen, sodass die Ergebnisse nicht pixelidentisch sind.

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

Fehlersuche #

Ein eingeschränktes Layout kann auf etwas unerwartete Weise fehlschlagen. Da ein Constraint-Solver verwendet wird, kann der Solver Lösungen finden, die mathematisch korrekt sind, aber überhaupt nicht das sind, was der Benutzer will. Der übliche Versagensmodus besteht darin, dass alle Größen auf ihren kleinsten zulässigen Wert zusammenbrechen. Wenn dies passiert, hat dies einen von zwei Gründen:

  1. Es war nicht genug Platz für die Elemente, die Sie zeichnen wollten.

  2. Es gibt einen Fehler - öffnen Sie in diesem Fall ein Problem unter https://github.com/matplotlib/matplotlib/issues .

Wenn es einen Fehler gibt, melden Sie ihn bitte mit einem eigenständigen Beispiel, das keine externen Daten oder Abhängigkeiten (außer numpy) erfordert.

Hinweise zum Algorithmus #

Der Algorithmus für die Einschränkung ist relativ einfach, aber aufgrund der komplexen Art und Weise, wie wir eine Figur gestalten können, etwas komplex.

Das Layout in Matplotlib erfolgt mit Gridspecs über die GridSpecKlasse. Eine Gitterspezifikation ist eine logische Unterteilung der Figur in Zeilen und Spalten, wobei die relative Breite der Achsen in diesen Zeilen und Spalten durch width_ratios und height_ratios festgelegt wird .

In constrained_layout bekommt jede Gridspec ein damit verbundenes Layoutgrid. Das Layoutgrid hat eine Reihe von leftund - rightVariablen für jede Spalte und bottomund - topVariablen für jede Zeile, und außerdem hat es einen Rand für links, rechts, unten und oben. In jeder Reihe werden die unteren/oberen Ränder verbreitert, bis alle Dekorateure in dieser Reihe untergebracht sind. Ähnlich für Spalten und die linken/rechten Ränder.

Einfacher Fall: eine Achse #

Für eine einzelne Achse ist das Layout einfach. Es gibt ein Eltern-Layoutgrid für die Figur, das aus einer Spalte und einer Reihe besteht, und ein Kind-Layoutgrid für die Gridspec, die die Achsen enthält, wiederum bestehend aus einer Reihe und einer Spalte. Auf jeder Seite der Achsen wird Platz für die "Dekorationen" geschaffen. Im Code wird dies durch die Einträge in do_constrained_layout()like erreicht:

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

wo bboxist der enge Begrenzungsrahmen der Achsen und posseine 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)
Titel

Einfacher Fall: zwei Achsen #

Wenn mehrere Achsen vorhanden sind, werden ihre Layouts auf einfache Weise gebunden. In diesem Beispiel hat die linke Achse viel größere Dekorationen als die rechte, aber sie teilen sich einen unteren Rand, der groß genug gemacht wird, um das größere xlabel aufzunehmen. Gleiches gilt für den gemeinsamen oberen Rand. Der linke und der rechte Rand 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)
Titel, Titel

Zwei Achsen und Farbbalken #

Ein Farbbalken ist einfach ein weiteres Element, das den Rand der übergeordneten Zelle des Layoutrasters 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)
Leitfaden für eingeschränkte Layouts

Mit einer Rasterspezifikation verknüpfter Farbbalken #

Wenn ein Farbbalken zu mehr als einer Zelle des Rasters gehört, dann macht er für jede einen größeren Rand:

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)
Leitfaden für eingeschränkte Layouts

Ungleich große Äxte #

Es gibt zwei Möglichkeiten, Achsen in einem Gridspec-Layout eine ungleichmäßige Größe zu geben, entweder indem Sie sie so angeben, dass sie Gridspecs-Zeilen oder -Spalten kreuzen, oder indem Sie Breiten- und Höhenverhältnisse angeben.

Hier wird die erste Methode verwendet. Beachten Sie, dass die Mitte topund die bottomRä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 nicht 1/2 der Höhe der linken Achsen. Dies steht im Einklang mit der Funktionsweise gridspecohne eingeschränktes 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)
Leitfaden für eingeschränkte Layouts

Ein Fall, der eine Verfeinerung erfordert, ist, wenn Ränder keine Künstler haben, die ihre Breite einschränken. Im folgenden Fall haben der rechte Rand für Spalte 0 und der linke Rand für Spalte 3 keine Randkünstler, um ihre Breite festzulegen, also nehmen wir die maximale Breite der Randbreiten, die Künstler haben. Dadurch haben alle Achsen die gleiche Größe:

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()
Titel

Gesamtlaufzeit des Skripts: ( 0 Minuten 18.885 Sekunden)

Galerie generiert von Sphinx-Gallery