HOWTO · Matplotlib
Cómo crear una única leyenda para todas las subtramas de Matplotlib
`fig.legend()` crea una leyenda para toda la figura de Matplotlib y puede reunir elementos de uno o varios Axes. En cambio, `ax.legend()` crea una leyenda para un Axes concreto. Si todos los subgráficos muestran las mismas series y etiquetas, basta con reutilizar los elementos y las etiquetas de uno de ellos.
En esta página
Usa fig.legend() para asociar una sola leyenda a toda la figura de Matplotlib. Si todos los subgráficos muestran las mismas series etiquetadas, reutiliza los elementos de leyenda y las etiquetas de un Axes. Si muestran series distintas, recopila los elementos y las etiquetas de cada Axes y pasa ambas listas a la leyenda de la figura. Esto se diferencia de ax.legend(), que crea una leyenda para un único Axes.
Los ejemplos siguientes usan Matplotlib para crear las figuras. El primero también imprime las etiquetas recopiladas para la leyenda compartida.
Crear una leyenda compartida para toda la figura cuando los subgráficos usan las mismas etiquetas
Si cada subgráfico representa las mismas series con las mismas etiquetas, uno de ellos ya proporciona las entradas necesarias para una leyenda compartida. El ejemplo siguiente usa dos mediciones con escalas distintas, ambas etiquetadas como measurement. Como coinciden tanto la etiqueta como el significado, basta con tomar los elementos de leyenda del primer Axes. Asocia la leyenda a fig, en lugar de llamar a legend() en cada Axes, para mostrarla una sola vez en toda la figura.
Ejecuta este ejemplo:
El código y las etiquetas o salidas visibles de esta sección se mantienen en inglés.
import matplotlib
matplotlib.use("Agg")
import logging
# Ignore only Matplotlib's benign cold-start cache notice; other diagnostics
# remain visible on stderr.
class _FontCacheNoticeFilter(logging.Filter):
def filter(self, record):
return "Matplotlib is building the font cache; this may take a moment." not in record.getMessage()
logging.getLogger("matplotlib.font_manager").addFilter(_FontCacheNoticeFilter())
import matplotlib.pyplot as plt
fig, axes = plt.subplots(2, 1, figsize=(6, 4))
x = [0, 1, 2]
for ax, scale in zip(axes, [1, 2]):
ax.plot(x, [scale * value for value in x], label="measurement")
handles, labels = axes[0].get_legend_handles_labels()
fig.legend(handles, labels, loc="upper center")
fig.tight_layout(rect=(0, 0, 1, 0.9))
print("Legend entries:", labels)
plt.show()
Legend entries: ['measurement']
get_legend_handles_labels() devuelve dos listas emparejadas para los artistas etiquetados de ese Axes: una de elementos de leyenda y otra de etiquetas. Este método es conciso, pero solo representa las series presentes en el Axes elegido. Si otro subgráfico tiene una etiqueta o serie distinta, usa el método que recopila los datos de todos los Axes en la sección siguiente.
Recopilar elementos de leyenda y etiquetas de cada Axes cuando el contenido de los subgráficos difiere
Cuando distintos subgráficos contienen líneas etiquetadas diferentes, recopila los elementos de leyenda y las etiquetas de cada Axes dentro del mismo bucle. Las listas conservan la correspondencia por posición: el elemento situado en el índice i corresponde a la etiqueta situada en el índice i. El código siguiente produce dos entradas en la leyenda, una por cada línea.
Ejecuta este ejemplo:
El código y las etiquetas o salidas visibles de esta sección se mantienen en inglés.
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
fig, axes = plt.subplots(1, 2, figsize=(7, 3))
axes[0].plot([0, 1, 2], [0, 1, 4], label="quadratic")
axes[1].plot([0, 1, 2], [0, 1, 2], label="linear")
handles, labels = [], []
for ax in axes:
ax_handles, ax_labels = ax.get_legend_handles_labels()
handles.extend(ax_handles)
labels.extend(ax_labels)
fig.legend(handles, labels, loc="upper center", ncol=2)
fig.tight_layout(rect=(0, 0, 1, 0.88))
plt.show()
Este método recopila los artistas etiquetados de todos los Axes, por lo que una misma etiqueta puede aparecer más de una vez. Si las entradas repetidas representan el mismo concepto, selecciona un solo elemento de leyenda para cada etiqueta deseada antes de llamar a fig.legend(). En cambio, conserva las etiquetas distintas cuando ayuden a diferenciar las series. Para mostrar solo algunas líneas, pasa únicamente los elementos y las etiquetas correspondientes; la leyenda no tiene por qué incluir todas las líneas trazadas.
Colocar y dar formato a la leyenda de toda la figura
El argumento loc determina qué punto de la leyenda se alinea con el ancla. Por ejemplo, fig.legend(..., loc="upper center") centra la leyenda en la parte superior de la figura. Para controlar el ancla de forma explícita, usa bbox_to_anchor; en una leyenda de figura, sus coordenadas son relativas a la figura. Por ejemplo, fig.legend(handles, labels, loc="upper center", bbox_to_anchor=(0.5, 1.02)) sitúa la leyenda justo por encima del borde superior. Ajusta los valores del ancla para moverla y reserva espacio con fig.tight_layout(rect=(0, 0, 1, 0.9)) o fig.subplots_adjust(top=0.82) para que no tape el contenido de los subgráficos.
El estilo de la leyenda usa opciones conocidas de otras leyendas de Matplotlib. Pasa valores como fontsize=9, frameon=False o facecolor="white" a fig.legend() para ajustar el tamaño del texto, el marco o su fondo. Al guardar una figura con una leyenda fuera de sus límites, fig.savefig("plot.png", bbox_inches="tight") puede incluirla en la imagen guardada.
Preguntas frecuentes sobre una leyenda de toda la figura
¿Qué diferencia hay entre ax.legend() y fig.legend()? ax.legend() pertenece a un Axes concreto. fig.legend() pertenece a la Figure y puede combinar entradas proporcionadas por uno o varios Axes.
¿Cómo creo una sola leyenda cuando todos los subgráficos usan las mismas etiquetas? Obtén los elementos de leyenda y las etiquetas de un Axes representativo y pásalos a fig.legend(). Esto funciona cuando ese Axes contiene las mismas series etiquetadas que los demás subgráficos.
¿Cómo incluyo solo algunas líneas? Conserva los elementos de leyenda y las etiquetas que quieras en listas emparejadas y pásalas a fig.legend(). Si hay etiquetas repetidas, determina si sus entradas representan la misma serie antes de eliminar duplicados.
¿Cómo evito que la leyenda tape los gráficos? Colócala en el margen de la figura con loc y bbox_to_anchor, y reserva espacio en la distribución de los subgráficos. Si queda fuera del lienzo, usa un cuadro delimitador ajustado al guardar para que no se recorte.