Legendenführer #

Legenden flexibel in Matplotlib generieren.

Diese Anleitung zur Legende ist eine Erweiterung der Dokumentation, die unter verfügbar ist legend()– stellen Sie bitte sicher, dass Sie mit dem Inhalt dieser Dokumentation vertraut sind, bevor Sie mit dieser Anleitung fortfahren.

In diesem Leitfaden werden einige gebräuchliche Begriffe verwendet, die hier zur Verdeutlichung dokumentiert sind:

Legendeneintrag #

Eine Legende besteht aus einem oder mehreren Legendeneinträgen. Ein Eintrag besteht aus genau einem Schlüssel und einem Label.

Legendenschlüssel #

Die farbige/gemusterte Markierung links neben jeder Legendenbeschriftung.

Legendenbezeichnung #

Der Text, der das durch den Schlüssel dargestellte Handle beschreibt.

Legendenhandle #

Das Originalobjekt, das verwendet wird, um einen entsprechenden Eintrag in der Legende zu erzeugen.

Kontrolle der Legendeneinträge #

Beim Aufrufen legend()ohne Argumente werden automatisch die Legendengriffe und die zugehörigen Beschriftungen abgerufen. Diese Funktionalität ist äquivalent zu:

handles, labels = ax.get_legend_handles_labels()
ax.legend(handles, labels)

Die get_legend_handles_labels()Funktion gibt eine Liste von Handles/Künstlern zurück, die auf den Achsen vorhanden sind, die verwendet werden können, um Einträge für die resultierende Legende zu generieren - es ist jedoch erwähnenswert, dass nicht alle Künstler zu einer Legende hinzugefügt werden können, an diesem Punkt wird ein "Proxy" verwendet müssen erstellt werden ( weitere Einzelheiten finden Sie unter Erstellen von Künstlern speziell zum Hinzufügen zur Legende (auch bekannt als Proxy-Künstler ).

Notiz

Künstler mit einer leeren Zeichenkette als Label oder mit einem Label, das mit einem Unterstrich "_" beginnt, werden ignoriert.

Um die volle Kontrolle darüber zu haben, was der Legende hinzugefügt wird, ist es üblich, die entsprechenden Griffe direkt an Folgendes zu übergeben legend():

fig, ax = plt.subplots()
line_up, = ax.plot([1, 2, 3], label='Line 2')
line_down, = ax.plot([3, 2, 1], label='Line 1')
ax.legend(handles=[line_up, line_down])

In einigen Fällen ist es nicht möglich, das Label des Handles festzulegen, daher ist es möglich, die Liste der Labels zu durchlaufen legend():

fig, ax = plt.subplots()
line_up, = ax.plot([1, 2, 3], label='Line 2')
line_down, = ax.plot([3, 2, 1], label='Line 1')
ax.legend([line_up, line_down], ['Line Up', 'Line Down'])

Erstellen von Künstlern speziell zum Hinzufügen zur Legende (auch bekannt als Proxy-Künstler) #

Nicht alle Griffe können automatisch in Legendeneinträge umgewandelt werden, daher ist es oft notwendig, einen Künstler zu erstellen, der dies kann . Legendengriffe müssen nicht auf der Figur oder den Äxten vorhanden sein, um verwendet zu werden.

Angenommen, wir wollten eine Legende erstellen, die einen Eintrag für einige Daten enthält, die durch eine rote Farbe dargestellt werden:

import matplotlib.patches as mpatches
import matplotlib.pyplot as plt

fig, ax = plt.subplots()
red_patch = mpatches.Patch(color='red', label='The red data')
ax.legend(handles=[red_patch])

plt.show()
Legende Führer

Es gibt viele unterstützte Legendengriffe. Anstatt einen Farbfleck zu erstellen, hätten wir auch eine Linie mit einem Marker erstellen können:

import matplotlib.lines as mlines

fig, ax = plt.subplots()
blue_line = mlines.Line2D([], [], color='blue', marker='*',
                          markersize=15, label='Blue stars')
ax.legend(handles=[blue_line])

plt.show()
Legende Führer

Legendenstandort #

Der Ort der Legende kann durch das Schlüsselwortargument loc angegeben werden . legend()Weitere Einzelheiten finden Sie in der Dokumentation unter .

Das bbox_to_anchorSchlüsselwort bietet ein hohes Maß an Kontrolle für die manuelle Legendenplatzierung. Wenn Sie beispielsweise möchten, dass sich Ihre Achsenlegende in der oberen rechten Ecke der Figur befindet und nicht in der Ecke der Achsen, geben Sie einfach die Position der Ecke und das Koordinatensystem dieser Position an:

ax.legend(bbox_to_anchor=(1, 1),
          bbox_transform=fig.transFigure)

Weitere Beispiele für benutzerdefinierte Legendenplatzierung:

fig, ax_dict = plt.subplot_mosaic([['top', 'top'], ['bottom', 'BLANK']],
                                  empty_sentinel="BLANK")
ax_dict['top'].plot([1, 2, 3], label="test1")
ax_dict['top'].plot([3, 2, 1], label="test2")
# Place a legend above this subplot, expanding itself to
# fully use the given bounding box.
ax_dict['top'].legend(bbox_to_anchor=(0., 1.02, 1., .102), loc='lower left',
                      ncol=2, mode="expand", borderaxespad=0.)

ax_dict['bottom'].plot([1, 2, 3], label="test1")
ax_dict['bottom'].plot([3, 2, 1], label="test2")
# Place a legend to the right of this smaller subplot.
ax_dict['bottom'].legend(bbox_to_anchor=(1.05, 1),
                         loc='upper left', borderaxespad=0.)

plt.show()
Legende Führer

Mehrere Legenden auf denselben Achsen #

Manchmal ist es übersichtlicher, Legendeneinträge auf mehrere Legenden aufzuteilen. Während der instinktive Ansatz dazu darin bestehen könnte, die legend()Funktion mehrmals aufzurufen, werden Sie feststellen, dass auf den Axes immer nur eine Legende existiert. Dies wurde so gemacht, dass es möglich ist, legend()wiederholt aufzurufen, um die Legende auf die neuesten Griffe auf den Achsen zu aktualisieren. Um alte Legendeninstanzen zu behalten, müssen wir sie manuell zu den Achsen hinzufügen:

fig, ax = plt.subplots()
line1, = ax.plot([1, 2, 3], label="Line 1", linestyle='--')
line2, = ax.plot([3, 2, 1], label="Line 2", linewidth=4)

# Create a legend for the first line.
first_legend = ax.legend(handles=[line1], loc='upper right')

# Add the legend manually to the Axes.
ax.add_artist(first_legend)

# Create another legend for the second line.
ax.legend(handles=[line2], loc='lower right')

plt.show()
Legende Führer

Legendenhandler #

Um Legendeneinträge zu erstellen, werden Handles als Argument an eine geeignete HandlerBaseUnterklasse übergeben. Die Wahl der Handler-Unterklasse wird durch die folgenden Regeln bestimmt:

  1. Aktualisieren Sie get_legend_handler_map() mit dem Wert im handler_mapSchlüsselwort.

  2. Überprüfen Sie, ob die handlein der neu erstellten handler_map.

  3. Überprüfen Sie, ob der Typ von handlein der neu erstellten handler_map.

  4. Überprüfen Sie, ob einer der Typen in der handlemro in der neu erstellten Datei enthalten ist handler_map.

Der Vollständigkeit halber ist diese Logik größtenteils in implementiert get_legend_handler().

All diese Flexibilität bedeutet, dass wir über die notwendigen Hooks verfügen, um benutzerdefinierte Handler für unsere eigene Art von Legendenschlüssel zu implementieren.

Das einfachste Beispiel für die Verwendung benutzerdefinierter Handler ist die Instanziierung einer der vorhandenen legend_handler.HandlerBaseUnterklassen. Lassen Sie uns der Einfachheit halber auswählen, welches ein numpointslegend_handler.HandlerLine2D -Argument akzeptiert (numpoints ist der Einfachheit halber auch ein Schlüsselwort für die Funktion). Wir können dann die Zuordnung der Instanz zum Handler als Schlüsselwort zur Legende übergeben.legend()

from matplotlib.legend_handler import HandlerLine2D

fig, ax = plt.subplots()
line1, = ax.plot([3, 2, 1], marker='o', label='Line 1')
line2, = ax.plot([1, 2, 3], marker='o', label='Line 2')

ax.legend(handler_map={line1: HandlerLine2D(numpoints=4)})
Legende Führer
<matplotlib.legend.Legend object at 0x7f2cf9a16ef0>

Wie Sie sehen können, hat "Linie 1" jetzt 4 Markierungspunkte, während "Linie 2" 2 hat (Standard). Versuchen Sie den obigen Code, ändern Sie nur den Schlüssel der Karte von line1zu type(line1). Beachten Sie, dass jetzt beide Line2DInstanzen 4 Markierungen erhalten.

Neben Handlern für komplexe Diagrammtypen wie Fehlerbalken, Stammdiagramme und Histogramme verfügt der Standard handler_mapüber einen speziellen tupleHandler ( legend_handler.HandlerTuple), der einfach die Handles für jedes Element im gegebenen Tupel übereinander zeichnet. Das folgende Beispiel demonstriert das Kombinieren zweier Legendenschlüssel übereinander:

from numpy.random import randn

z = randn(10)

fig, ax = plt.subplots()
red_dot, = ax.plot(z, "ro", markersize=15)
# Put a white cross over some of the data.
white_cross, = ax.plot(z[:5], "w+", markeredgewidth=3, markersize=15)

ax.legend([red_dot, (red_dot, white_cross)], ["Attr A", "Attr A+B"])
Legende Führer
<matplotlib.legend.Legend object at 0x7f2cfb693760>

Die legend_handler.HandlerTupleKlasse kann auch verwendet werden, um demselben Eintrag mehrere Legendenschlüssel zuzuweisen:

from matplotlib.legend_handler import HandlerLine2D, HandlerTuple

fig, ax = plt.subplots()
p1, = ax.plot([1, 2.5, 3], 'r-d')
p2, = ax.plot([3, 2, 1], 'k-o')

l = ax.legend([(p1, p2)], ['Two keys'], numpoints=1,
              handler_map={tuple: HandlerTuple(ndivide=None)})
Legende Führer

Implementieren eines benutzerdefinierten Legenden-Handlers #

Ein benutzerdefinierter Handler kann implementiert werden, um jedes Handle in einen Legendenschlüssel umzuwandeln (Handles müssen nicht unbedingt Matplotlib-Künstler sein). Der Handler muss eine legend_artistMethode implementieren, die einen einzelnen Künstler zurückgibt, den die Legende verwenden soll. Die erforderliche Signatur für legend_artistist unter dokumentiert legend_artist.

import matplotlib.patches as mpatches


class AnyObject:
    pass


class AnyObjectHandler:
    def legend_artist(self, legend, orig_handle, fontsize, handlebox):
        x0, y0 = handlebox.xdescent, handlebox.ydescent
        width, height = handlebox.width, handlebox.height
        patch = mpatches.Rectangle([x0, y0], width, height, facecolor='red',
                                   edgecolor='black', hatch='xx', lw=3,
                                   transform=handlebox.get_transform())
        handlebox.add_artist(patch)
        return patch

fig, ax = plt.subplots()

ax.legend([AnyObject()], ['My first handler'],
          handler_map={AnyObject: AnyObjectHandler()})
Legende Führer
<matplotlib.legend.Legend object at 0x7f2cddb26a10>

Hätten wir alternativ Instanzen global akzeptieren wollen, ohne das Schlüsselwort handler_mapAnyObject ständig manuell setzen zu müssen , hätten wir den neuen Handler registrieren können mit:

from matplotlib.legend import Legend
Legend.update_default_handler_map({AnyObject: AnyObjectHandler()})

Während die Macht hier klar ist, denken Sie daran, dass bereits viele Handler implementiert sind und das, was Sie erreichen möchten, möglicherweise bereits mit vorhandenen Klassen problemlos möglich ist. Um beispielsweise elliptische statt rechteckige Legendenschlüssel zu erstellen:

from matplotlib.legend_handler import HandlerPatch


class HandlerEllipse(HandlerPatch):
    def create_artists(self, legend, orig_handle,
                       xdescent, ydescent, width, height, fontsize, trans):
        center = 0.5 * width - 0.5 * xdescent, 0.5 * height - 0.5 * ydescent
        p = mpatches.Ellipse(xy=center, width=width + xdescent,
                             height=height + ydescent)
        self.update_prop(p, orig_handle, legend)
        p.set_transform(trans)
        return [p]


c = mpatches.Circle((0.5, 0.5), 0.25, facecolor="green",
                    edgecolor="red", linewidth=3)

fig, ax = plt.subplots()

ax.add_patch(c)
ax.legend([c], ["An ellipse, not a rectangle"],
          handler_map={mpatches.Circle: HandlerEllipse()})
Legende Führer
<matplotlib.legend.Legend object at 0x7f2d00dde710>

Gesamtlaufzeit des Skripts: (0 Minuten 3,053 Sekunden)

Galerie generiert von Sphinx-Gallery