Notiz
Klicken Sie hier , um den vollständigen Beispielcode herunterzuladen
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()
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()
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_anchor
Schlü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:
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()
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()
Legendenhandler #
Um Legendeneinträge zu erstellen, werden Handles als Argument an eine geeignete HandlerBase
Unterklasse übergeben. Die Wahl der Handler-Unterklasse wird durch die folgenden Regeln bestimmt:
Aktualisieren Sie
get_legend_handler_map()
mit dem Wert imhandler_map
Schlüsselwort.Überprüfen Sie, ob die
handle
in der neu erstelltenhandler_map
.Überprüfen Sie, ob der Typ von
handle
in der neu erstelltenhandler_map
.Überprüfen Sie, ob einer der Typen in der
handle
mro in der neu erstellten Datei enthalten isthandler_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.HandlerBase
Unterklassen. 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)})
<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 line1
zu
type(line1)
. Beachten Sie, dass jetzt beide Line2D
Instanzen 4 Markierungen erhalten.
Neben Handlern für komplexe Diagrammtypen wie Fehlerbalken, Stammdiagramme und Histogramme verfügt der Standard handler_map
über einen speziellen tuple
Handler ( 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"])
<matplotlib.legend.Legend object at 0x7f2cfb693760>
Die legend_handler.HandlerTuple
Klasse 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)})
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_artist
Methode implementieren, die einen einzelnen Künstler zurückgibt, den die Legende verwenden soll. Die erforderliche Signatur für legend_artist
ist 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()})
<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()})
<matplotlib.legend.Legend object at 0x7f2d00dde710>
Gesamtlaufzeit des Skripts: (0 Minuten 3,053 Sekunden)