Skip to content
Temas
Matplotlib
Matplotlib Legend Outside the Plot: bbox_to_anchor Cheatsheet

Leyenda de Matplotlib fuera del gráfico: chuleta de bbox_to_anchor

Publicado el

Actualizado el

Mueve la leyenda de Matplotlib fuera de los ejes con bbox_to_anchor y loc. Colócala a la derecha, a la izquierda o debajo del gráfico, reduce los ejes si hace falta y exporta con bbox_inches='tight' para que no se recorte.

Las leyendas por defecto van dentro de los ejes y a menudo tapan los datos. Para dejar la leyenda fuera, combina loc (qué esquina del cuadro de la leyenda es el ancla) con bbox_to_anchor (dónde se coloca ese ancla en coordenadas de los ejes).

Solución rápida

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()
ColocaciónLlamada típica
A la derecha de los ejeslegend(bbox_to_anchor=(1.02, 1), loc="upper left")
Derecha, centrada en verticallegend(loc="center left", bbox_to_anchor=(1.02, 0.5))
Debajo, horizontallegend(loc="upper center", bbox_to_anchor=(0.5, -0.12), ncol=n)
Arribalegend(loc="lower center", bbox_to_anchor=(0.5, 1.02), ncol=n)
Exportar sin recortessavefig(..., bbox_inches="tight") o tight_layout() / constrained_layout=True

Coordenadas de los ejes: (0, 0) es la esquina inferior izquierda de los ejes, (1, 1) la superior derecha. Valores un poco por encima de 1 o por debajo de 0 quedan justo fuera del marco del gráfico.

El problema: la leyenda encima de los datos

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

Default Matplotlib legend inside the axes

loc="best" solo elige la esquina interna menos mala. Nunca saca la leyenda al margen de la figura.

Cómo trabajan juntos bbox_to_anchor y loc

  1. bbox_to_anchor=(x, y) — punto en coordenadas fraccionarias de los ejes (por defecto).
  2. loc="upper left" (etc.) — qué punto del cuadro de la leyenda se fija a ese ancla.
  3. borderaxespad — padding entre los ejes y la leyenda; pon 0 cuando quieras un anclaje justito por fuera.

Modelo mental: punto de ancla en el gráfico + qué esquina de la leyenda se sienta en ese punto.

Colocar la leyenda a la derecha

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

Legend placed outside to the right of the axes

Si la ventana sigue recortando la leyenda, llama a tight_layout() / usa constrained_layout=True en subplots, o reserva espacio reduciendo los ejes (siguiente sección).

Reduce los ejes y luego ancla la leyenda

Cuando tienes muchas series, deja una columna dedicada a la leyenda:

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

Axes shrunk with legend docked on the right

Alternativa moderna: crea la figura con motores de layout que cooperan mejor con artistas fuera de los ejes:

fig, ax = plt.subplots(layout="constrained")
# ... plot ...
ax.legend(bbox_to_anchor=(1.02, 1), loc="upper left")

Leyenda debajo del gráfico (horizontal)

Usa ncol para que las entradas queden en una fila bajo el gráfico: bien para diapositivas y dashboards anchos:

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

Horizontal legend placed below the plot

Guía de decisión

SituaciónPrefiere
2–4 series, gráfico de líneas simplebbox_to_anchor=(1.02, 1), loc="upper left" + tight_layout()
Muchas series, layout estableReducir ejes / layout="constrained" + leyenda a la derecha
Figura ancha / presentaciónLeyenda inferior con ncol
Mapa o imagen donde cualquier caja molestaLeyenda interna semitransparente: framealpha=0.3 (compromiso)
Guardar PNG/PDF para papersPrueba siempre bbox_inches="tight" (abajo)

Trampa al exportar: la leyenda exterior desaparece en el archivo

Las ventanas interactivas pueden mostrar la leyenda mientras savefig la recorta. El arreglo habitual:

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

Saved figure that keeps the outside legend via bbox_inches tight

Profundidad relacionada: savefig recorta etiquetas. Si las etiquetas siguen chocando, sube el tamaño de figura antes de microajustar anclas.

Controles extra (sin mover el cuadro)

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 — leyenda en varias columnas
  • framealpha — transparencia cuando debas dejar la leyenda sobre los datos
  • title — etiqueta de grupo para gráficos multi-serie

Para estilos de leyenda en general (no solo posición), ver Matplotlib legend.

Trampas frecuentes

TrampaQué vesArreglo
Solo pones loc="right"La leyenda sigue dentroNecesitas bbox_to_anchor más allá de 1.0
Leyenda fuera en la GUI, ausente en el PNGExportación recortadabbox_inches="tight" o constrained layout
bbox_to_anchor en coords de datos por errorLa leyenda se va volandoPor defecto son coords de ejes; pasa una 2-tupla, no un Bbox salvo que sea a propósito
Fuente enorme de leyendaDomina la figurafontsize=8–10, o menos columnas
Solapamiento con colorbarMargen aplastadoReserva espacio para ambos, o pon la leyenda debajo

FAQ

Conclusión

Las leyendas fuera son un problema de layout, no una API misteriosa: fija una esquina de la leyenda con loc, coloca ese pin con bbox_to_anchor justo más allá de los ejes (> 1 o < 0), y asegúrate de que la exportación use layout tight/constrained para que el margen sobreviva en el archivo. Usa una pila a la derecha para muchas series y una fila inferior con ncol para figuras anchas.

Related Guides