Matplotlib Legende außerhalb des Plots: bbox_to_anchor Cheatsheet
Veröffentlicht am
Aktualisiert am

Standard-Legenden sitzen innerhalb der Achsen und verdecken oft Daten. Um die Legende außerhalb zu parken, loc (welche Ecke der Legendenbox der Anker ist) mit bbox_to_anchor (wo dieser Anker in Achsenkoordinaten liegt) kombinieren.
Schnelle Lösung
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 200)
fig, ax = plt.subplots()
ax.plot(x, np.sin(x), label="sin(x)")
ax.plot(x, np.cos(x), label="cos(x)")
# Outside, upper-right of the axes
ax.legend(bbox_to_anchor=(1.02, 1), loc="upper left", borderaxespad=0)
plt.tight_layout()
plt.show()| Platzierung | Typischer Aufruf |
|---|---|
| Rechts der Achsen | legend(bbox_to_anchor=(1.02, 1), loc="upper left") |
| Rechts, vertikal zentriert | legend(loc="center left", bbox_to_anchor=(1.02, 0.5)) |
| Unten, horizontal | legend(loc="upper center", bbox_to_anchor=(0.5, -0.12), ncol=n) |
| Oben | legend(loc="lower center", bbox_to_anchor=(0.5, 1.02), ncol=n) |
| Export ohne Abschneiden | savefig(..., bbox_inches="tight") oder tight_layout() / constrained_layout=True |
Achsenkoordinaten: (0, 0) ist die untere linke Ecke der Axes, (1, 1) die obere rechte. Werte leicht über 1 oder unter 0 liegen knapp außerhalb des Plot-Rahmens.
- Runcell Science: Open-Source-Alternative zu Claude Science für Forschungsteams
- Mac Ruhezustand verhindern: Codex, Claude Code und KI-Agenten weiterlaufen lassen
- OpenClaw vs ZeroClaw vs Pi Agent vs Nanobot: Welchen KI-Agenten-Stack sollten Sie 2026 wählen?
- Wie Claude Code Jupyter Notebooks analysiert: Data Science, Grenzen und die bessere Alternative
- Claude Code Routines: KI-Cronjobs für Agenten
- Claude Code Desktop: Bypass permissions aktivieren
- Schritt-für-Schritt-Anleitung zur Erstellung von zwei Python-Agenten mit Googles A2A-Protokoll
- Die Top 10 wachsenden Data Visualization Libraries in Python im Jahr 2025
Das Problem: Legende über den Daten
fig, ax = plt.subplots(figsize=(7, 4))
ax.plot(x, np.sin(x), label="sin(x)", lw=2)
ax.plot(x, np.cos(x), label="cos(x)", lw=2)
ax.legend(loc="best") # still inside the axes
ax.set_title("Default legend (often overlaps data)")
plt.show()
loc="best" wählt nur die am wenigsten schlechte innere Ecke. Die Legende wandert nie in den Figure-Rand.
Wie bbox_to_anchor und loc zusammenwirken
bbox_to_anchor=(x, y)— Punkt in Achsen-Bruchteilen (Standard).loc="upper left"(usw.) — welcher Punkt der Legendenbox an diesem Anker festgemacht wird.borderaxespad— Abstand zwischen Axes und Legende; auf0setzen für knappes Parken außen.
Denkmodell: Ankerpunkt am Plot + welche Ecke der Legende auf diesem Punkt sitzt.
Legende rechts platzieren
fig, ax = plt.subplots(figsize=(7, 4))
ax.plot(x, np.sin(x), label="sin(x)", lw=2)
ax.plot(x, np.cos(x), label="cos(x)", lw=2)
ax.legend(bbox_to_anchor=(1.02, 1), loc="upper left", borderaxespad=0)
ax.set_title("Legend outside: upper right of axes")
fig.tight_layout()
plt.show()
Schneidet das Fenster die Legende noch ab, tight_layout() aufrufen / constrained_layout=True in subplots nutzen oder Platz schaffen, indem die Axes verkleinert werden (nächster Abschnitt).
Axes verkleinern, dann Legende andocken
Bei vielen Serien dem Plot eine eigene Legenden-Spalte geben:
x = np.arange(10)
fig = plt.figure(figsize=(7.2, 4.2))
ax = fig.add_subplot(111)
for i in range(5):
ax.plot(x, i * x, label=f"y = {i}x", lw=2)
# Leave ~22% of the figure width for the legend
box = ax.get_position()
ax.set_position([box.x0, box.y0, box.width * 0.78, box.height])
ax.legend(loc="center left", bbox_to_anchor=(1.02, 0.5), borderaxespad=0)
ax.set_title("Shrink axes, legend to the right")
plt.show()
Moderne Alternative: Figure mit Layout-Engines erzeugen, die besser mit Künstlern außerhalb der Axes kooperieren:
fig, ax = plt.subplots(layout="constrained")
# ... plot ...
ax.legend(bbox_to_anchor=(1.02, 1), loc="upper left")Legende unter dem Plot (horizontal)
Mit ncol sitzen die Einträge in einer Reihe unter dem Chart — gut für Folien und breite Dashboards:
x = np.arange(10)
fig = plt.figure(figsize=(7.2, 4.4))
ax = fig.add_subplot(111)
for i in range(5):
ax.plot(x, i * x, label=f"y = {i}x", lw=2)
box = ax.get_position()
ax.set_position([box.x0, box.y0 + box.height * 0.12, box.width, box.height * 0.88])
ax.legend(loc="upper center", bbox_to_anchor=(0.5, -0.12), ncol=5)
ax.set_title("Horizontal legend below the plot")
plt.show()
Entscheidungsleitfaden
| Situation | Bevorzugen |
|---|---|
| 2–4 Serien, einfaches Liniendiagramm | bbox_to_anchor=(1.02, 1), loc="upper left" + tight_layout() |
| Viele Serien, stabiles Layout | Axes verkleinern / layout="constrained" + rechte Legende |
| Breite Figure / Präsentation | untere Legende mit ncol |
| Karte/Bild, bei dem jede Box stört | halbtransparente innere Legende: framealpha=0.3 (Kompromiss) |
| PNG/PDF für Papers speichern | immer bbox_inches="tight" testen (unten) |
Export-Falle: Außenlegende fehlt in der Datei
Im interaktiven Fenster kann die Legende sichtbar sein, während savefig sie abschneidet. Der übliche Fix:
fig, ax = plt.subplots(figsize=(7, 4))
ax.plot(x, np.sin(x), label="sin(x)", lw=2)
ax.plot(x, np.cos(x), label="cos(x)", lw=2)
ax.legend(bbox_to_anchor=(1.02, 1), loc="upper left", borderaxespad=0)
ax.set_title("Outside legend kept with bbox_inches='tight'")
fig.savefig("legend-outside.png", dpi=150, bbox_inches="tight", facecolor="white")
Verwandter Deep Dive: savefig schneidet Labels ab. Kollidieren Labels weiterhin, die Figure-Größe erhöhen, bevor man Anker-Koordinaten feinjustiert.
Extra-Steuerung (ohne die Box zu verschieben)
ax.legend(
bbox_to_anchor=(1.02, 1),
loc="upper left",
borderaxespad=0,
frameon=True,
fancybox=False,
framealpha=0.95,
fontsize=9, # or prop={"size": 9}
title="Series",
alignment="left",
)ncol— mehrspaltige Legendeframealpha— Transparenz, wenn die Legende über Daten bleiben musstitle— Gruppenlabel bei Multi-Serien-Charts
Für allgemeines Legend-Styling (nicht nur Position) siehe Matplotlib Legend.
Typische Fallen
| Falle | Was man sieht | Fix |
|---|---|---|
Nur loc="right" gesetzt | Legende bleibt innen | bbox_to_anchor jenseits von 1.0 nötig |
| Außenlegende in der GUI, fehlt im PNG | beschnittener Export | bbox_inches="tight" oder constrained layout |
bbox_to_anchor versehentlich in Datenkoordinaten | Legende fliegt weg | Standard sind Achsenkoordinaten; 2-Tupel übergeben, kein Bbox, außer absichtlich |
| Riesige Legendenschrift | dominiert die Figure | fontsize=8–10 oder weniger Spalten |
| Überlappung mit Colorbar | gequetschter Rand | Platz für beides reservieren oder Legende nach unten |
FAQ
Fazit
Außenlegenden sind ein Layout-Problem, keine geheimnisvolle API: eine Legendenecke mit loc anpinnen, diesen Pin mit bbox_to_anchor knapp jenseits der Axes setzen (> 1 oder < 0), und beim Export tight/constrained Layout nutzen, damit der Rand in der Datei erhalten bleibt. Bei vielen Serien einen rechten Stapel, bei breiten Figures eine untere ncol-Reihe.
Verwandte Anleitungen
- Matplotlib Legend — Styling, Titel und Multi-Legend-Muster
- Matplotlib savefig schneidet Labels ab — Export-Clipping-Checkliste
- Matplotlib Figure-Größe — Legenden Platz geben, bevor Anker feinjustiert werden
- Matplotlib fill_between — schattierte Serien, die klare Legenden brauchen
- Matplotlib mehrere Linienplots — Multi-Serien-Charts, die dieses Problem auslösen
- Matplotlib Annotationen und Text — Labels, wenn eine Legende nicht reicht
- Matplotlib Subplots — gemeinsame Legenden über Panels