HOWTO · Matplotlib

Cómo colocar una leyenda fuera de los ejes en Matplotlib

Aprende a colocar una leyenda de Matplotlib fuera de los ejes y a evitar que se recorte al guardar la figura.

En esta página

Usa bbox_to_anchor junto con loc para colocar una leyenda de Matplotlib fuera de los ejes. Por ejemplo, ax.legend(loc="upper left", bbox_to_anchor=(1.02, 1)) sitúa la esquina superior izquierda de la leyenda justo más allá del borde superior derecho de los ejes. En el sistema de coordenadas predeterminado de los ejes, (0, 0) corresponde a la esquina inferior izquierda y (1, 1), a la superior derecha.

Ejemplo de bbox_to_anchor

Usa un bbox_to_anchor de dos valores para colocar la leyenda justo fuera de los ejes. En Axes.legend, el par representa un punto de anclaje en las coordenadas de los ejes; loc alinea con ese punto la esquina correspondiente de la leyenda. Este ejemplo completo dibuja dos curvas con etiquetas y reserva espacio en la figura para la leyenda.

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)
fig, ax = plt.subplots()
ax.plot(x, np.sin(x), label="sin(x)")
ax.plot(x, np.cos(x), label="cos(x)")
ax.legend(loc="upper left", bbox_to_anchor=(1.02, 1))
fig.subplots_adjust(right=0.78)
plt.close(fig)

Ejemplo de la leyenda de Matplotlib con bbox_to_anchor

Para ajustar la posición con más precisión, bbox_to_anchor también acepta (x0, y0, width, height). Esta tupla define un cuadro de anclaje, no las dimensiones de la leyenda: (x0, y0) es la esquina inferior izquierda del cuadro, mientras que width y height determinan su tamaño en coordenadas de los ejes. loc elige el punto de la leyenda que se alinea con el punto correspondiente del cuadro. Por ejemplo, loc="upper left" alinea la esquina superior izquierda de la leyenda con la esquina superior izquierda del cuadro. Algunos valores de cadena habituales son "upper right", "lower left", "center" y "best"; Matplotlib también acepta sus códigos numéricos, del 0 para "best" al 10 para "center".

tight_layout() ajusta los parámetros de los subgráficos para dejar espacio a elementos de los ejes, como las etiquetas y los títulos. No reserva de forma fiable espacio para una leyenda externa en todas las distribuciones. Para mantener visible la leyenda en una ventana, deja sitio con fig.subplots_adjust(right=...) o elige una distribución que acomode tanto los ejes como la leyenda. La primera imagen muestra una leyenda externa; la imagen del resultado recortado ilustra lo que puede ocurrir si la figura no tiene espacio para ella.

Leyenda de Matplotlib recortada con bbox_to_anchor

bbox_extra_artists y bbox_inches para evitar que la caja de la leyenda sea recortada

Al guardar una figura, pasa la leyenda externa en bbox_extra_artists y establece bbox_inches="tight". Así, la operación de guardado tiene en cuenta la leyenda al calcular el cuadro delimitador ajustado de la figura, por lo que la imagen exportada la incluye. Este ejemplo se ejecutó correctamente y guarda el PNG en un directorio temporal. No genera salida estándar ni mensajes de error.

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
from pathlib import Path
from tempfile import TemporaryDirectory

x = np.linspace(0, 10, 100)
fig, ax = plt.subplots()
ax.plot(x, np.sin(x), label="sin(x)")
ax.plot(x, np.cos(x), label="cos(x)")
legend = ax.legend(loc="upper left", bbox_to_anchor=(1.02, 1))

with TemporaryDirectory() as directory:
    output_path = Path(directory) / "example.png"
    fig.savefig(
        output_path,
        dpi=300,
        format="png",
        bbox_extra_artists=(legend,),
        bbox_inches="tight",
    )

plt.close(fig)

bbox_extra_artists recibe los artistas que Matplotlib debe incluir al calcular el cuadro delimitador ajustado. bbox_inches="tight" indica a savefig que use ese cuadro calculado para la imagen guardada. Estas opciones evitan que la leyenda se recorte al exportar; no cambian su tamaño ni su posición dentro de los ejes.

El ejemplo de guardado terminó con código de salida 0 y tanto la salida estándar como la de error quedaron vacías, así que no hay una salida visible que mostrar.