Mi leyenda matplotlib.pyplot está siendo cortada

5 minutos de lectura

avatar de usuario
usuario1005909

Estoy intentando crear una trama con una leyenda al costado usando matplotlib. Puedo ver que se está creando la trama, pero los límites de la imagen no permiten que se muestre la leyenda completa.

lines = []
ax = plt.subplot(111)
for filename in args:
    lines.append(plt.plot(y_axis, x_axis, colors[colorcycle], linestyle="steps-pre", label=filename))
ax.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)

Esto produce:
ingrese la descripción de la imagen aquí

  • Esta respuesta proporciona una descripción general de varias técnicas que se pueden usar para que la leyenda aparezca dentro de los límites de la figura.

    – La Importancia De Ser Ernesto

    11/10/2017 a las 22:03


avatar de usuario
tirador

Aunque es tarde, quiero referirme a una buena alternativa recientemente introducida:

Nueva característica de matplotlib: el cuadro delimitador estrecho

Si está interesado en el archivo de salida de plt.savefig: en este caso la bandera bbox_inches="tight" ¡es tu amigo!

import matplotlib.pyplot as plt

fig = plt.figure(1)
plt.plot([1, 2, 3], [1, 0, 1], label="A")
plt.plot([1, 2, 3], [1, 2, 2], label="B")
plt.legend(loc="center left", bbox_to_anchor=(1, 0))

fig.savefig('samplefigure', bbox_inches="tight")

Archivo de salida: figura de muestra.png

Quiero referirme también a una respuesta más detallada: mover la leyenda de matplotlib fuera del eje hace que se corte en el cuadro de la figura

Ventajas

  • No hay necesidad de ajustar los datos/imagen reales.
  • es compatible con plt.subplots como-bien donde como los otros no estan!
  • Se aplica al menos a los archivos de salida más utilizados, por ejemplo, png, pdf.

  • ¡Gracias! Esto funcionó muy bien con pequeñas modificaciones necesarias.

    usuario402642

    8 de agosto de 2017 a las 23:27

  • @CarlodelMundo: ¿Qué modificaciones fueron necesarias en su caso? Gracias por compartir con nosotros.

    – stripper

    10 de agosto de 2017 a las 7:47

  • este debería ser el valor predeterminado para plt.savefig()

    – MaxS

    25 de abril de 2019 a las 9:13

  • funcionó, gracias! Solo como referencia, aquí está la documentación de matplotlib: > Bbox en pulgadas. Solo se guarda la parte dada de la figura. Si está ‘apretado’, trate de averiguar el recuadro estrecho de la figura. Si ninguno, use savefig.bbox ^^^ ¿qué significa eso? quien haya escrito esto debería recibir una patada en la cara.

    – Jonathan

    8 de julio de 2019 a las 21:59


  • Gracias, he estado buscando esto por años!

    – Marthe Veldhuis

    18 de enero de 2021 a las 16:35

Como señaló Adam, debe hacer un espacio al costado de su gráfico. Si desea afinar el espacio necesario, puede consultar la add_axes método de matplotlib.pyplot.artist.

A continuación se muestra un ejemplo rápido:

import matplotlib.pyplot as plt
import numpy as np

# some data
x = np.arange(0, 10, 0.1)
y1 = np.sin(x)
y2 = np.cos(x)

# plot of the data
fig = plt.figure()
ax = fig.add_axes([0.1, 0.1, 0.6, 0.75])
ax.plot(x, y1,'-k', lw=2, label="black sin(x)")
ax.plot(x, y2,'-r', lw=2, label="red cos(x)")
ax.set_xlabel('x', size=22)
ax.set_ylabel('y', size=22)
ax.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)

plt.show()

y la imagen resultante: imagen

  • Sé que a matplotlib le gusta promocionar que todo está bajo el control del usuario, pero todo esto con las leyendas es demasiado bueno. Si pongo la leyenda fuera, yo obviamente quiere que todavía sea visible. La ventana debería escalarse sola para ajustarse en lugar de crear esta enorme molestia de cambio de escala. Como mínimo, debería haber una opción True predeterminada para controlar este comportamiento de escalado automático. Obligar a los usuarios a pasar por una cantidad ridícula de renderizaciones para tratar de obtener los números de escala correctos en nombre del control logra lo contrario.

    – Elliot

    2 de enero de 2013 a las 21:43


  • @strpeter ha proporcionado una solución automática en su respuesta que funcionó perfectamente bien para mí.

    – Tim Trondle

    27 de febrero de 2017 a las 12:21

  • estoy mirando este código durante minutos y todavía no entiendo qué línea soluciona el problema

    – Jemshit Iskenderov

    22 de marzo de 2019 a las 20:28

Solo usa plt.tight_layout()

import matplotlib.pyplot as plt
    
fig = plt.figure(1)
plt.plot([1, 2, 3], [1, 0, 1], label="A")
plt.plot([1, 2, 3], [1, 2, 2], label="B")
plt.legend(loc="center left", bbox_to_anchor=(1, 0))

plt.tight_layout()

Esto probablemente se introdujo en el nuevo matplotlib versión y perfectamente hace el trabajo.

avatar de usuario
ecoe

Aquí hay otra forma de hacer espacio (reducir un eje):

# get the current axis
ax = plt.gca()
# Shink current axis by 20%
box = ax.get_position()
ax.set_position([box.x0, box.y0, box.width * 0.8, box.height])

donde 0.8 escala el ancho del eje en un 20%. En mi máquina win7 64, usar un factor mayor que 1 dejará espacio para la leyenda si está fuera de la trama.

Se hizo referencia a este código de: Cómo sacar la leyenda de la trama

avatar de usuario
carne_mecanica

Editar: @gcalmettes publicó una mejor respuesta.
Su solución probablemente debería usarse en lugar del método que se muestra a continuación.
No obstante, dejaré esto ya que a veces ayuda ver diferentes formas de hacer las cosas.


Como se muestra en la guía de trazado de leyendaspuede dejar espacio para otra trama secundaria y colocar la leyenda allí.

import matplotlib.pyplot as plt
ax = plt.subplot(121) # <- with 2 we tell mpl to make room for an extra subplot
ax.plot([1,2,3], color="red", label="thin red line")
ax.plot([1.5,2.5,3.5], color="blue", label="thin blue line")
ax.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
plt.show()

Produce:

ingrese la descripción de la imagen aquí

avatar de usuario
bufón

¿Honestamente? Creo que esto es quizás bastante simple y directo.

Simplemente almacene su instancia de llamada de leyenda en una variable. p.ej:

rr = sine_curve_plot.legend(loc=(0.0,1.1))

Luego, incluye la bbox_extra_artists, bbox_inches argumento de palabra clave para plt.savefig. es decir:

plt.savefig('output.pdf', bbox_inches="tight", bbox_extra_artists=(rr)) 

bbox_extra_artists acepta un iterable, por lo que puede incluir tantos legend instancias en él. los bbox_extra_artists automáticamente le dice a plt que cubra cada información adicional que se pasa a bbox_extra_artists.

DESCARGO DE RESPONSABILIDAD: El loc La variable simplemente define la posición de la leyenda, puede modificar los valores para una mayor flexibilidad en el posicionamiento. Por supuesto, cadenas como upper left, upper rightetc. también son válidos.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad