Programmatische Steuerung der Subplot-Anpassung#

Hinweis

Dieses Beispiel soll in erster Linie einige fortgeschrittene Konzepte in Matplotlib zeigen.

Wenn Sie nur nach ausreichend Platz für Ihre Beschriftungen suchen, ist es fast immer einfacher und ausreichend, die Subplot-Parameter entweder manuell mit Figure.subplots_adjust festzulegen oder einen der automatischen Layout-Mechanismen zu verwenden (Leitfaden für eingeschränkte Layouts oder Leitfaden für straffe Layouts).

Dieses Beispiel beschreibt eine benutzerdefinierte Methode, um die Größen von Künstlern auszulesen und die Subplot-Parameter entsprechend einzustellen. Sein Hauptzweck ist es, einige fortgeschrittene Konzepte wie das Auslesen von Textpositionen, die Arbeit mit Bounding Boxes und Transformationen sowie die Verwendung von Events zu veranschaulichen. Es kann aber auch als Ausgangspunkt dienen, wenn Sie das Layout automatisieren möchten und mehr Flexibilität als bei Tight Layout und Constrained Layout benötigen.

Unten sammeln wir die Bounding Boxes aller y-Achsen-Beschriftungen und verschieben den linken Rand des Subplots nach rechts, sodass genügend Platz für die Vereinigung aller Bounding Boxes bleibt.

Es gibt einen Haken bei der Berechnung von Text-Bounding-Boxes: Das Abfragen der Text-Bounding-Boxes (Text.get_window_extent) benötigt einen Renderer (RendererBase-Instanz), um die Textgröße zu berechnen. Dieser Renderer ist erst verfügbar, nachdem die Abbildung gezeichnet wurde (Figure.draw).

Eine Lösung dafür ist, die Anpassungslogik in einen Draw-Callback zu legen. Diese Funktion wird ausgeführt, nachdem die Abbildung gezeichnet wurde. Sie kann nun prüfen, ob der Subplot genügend Platz für den Text lässt. Wenn nicht, werden die Subplot-Parameter aktualisiert und ein zweiter Draw ausgelöst.

import matplotlib.pyplot as plt

import matplotlib.transforms as mtransforms

fig, ax = plt.subplots()
ax.plot(range(10))
ax.set_yticks([2, 5, 7], labels=['really, really, really', 'long', 'labels'])


def on_draw(event):
    bboxes = []
    for label in ax.get_yticklabels():
        # Bounding box in pixels
        bbox_px = label.get_window_extent()
        # Transform to relative figure coordinates. This is the inverse of
        # transFigure.
        bbox_fig = bbox_px.transformed(fig.transFigure.inverted())
        bboxes.append(bbox_fig)
    # the bbox that bounds all the bboxes, again in relative figure coords
    bbox = mtransforms.Bbox.union(bboxes)
    if fig.subplotpars.left < bbox.width:
        # Move the subplot left edge more to the right
        fig.subplots_adjust(left=1.1*bbox.width)  # pad a little
        fig.canvas.draw()


fig.canvas.mpl_connect('draw_event', on_draw)

plt.show()
auto subplots adjust

Tags: Komponente: Subplot Plot-Typ: Linie Styling: Position Level: Fortgeschritten

Galerie generiert von Sphinx-Gallery