matrices libreria hacer graficos graficar example como python matplotlib legend

python - libreria - matplotlib legend example



Cómo sacar a la leyenda de la trama. (16)

Colocando la leyenda ( bbox_to_anchor )

Una leyenda se coloca dentro del cuadro delimitador de los ejes utilizando el argumento loc para plt.legend .
Por ejemplo, loc="upper right" coloca la leyenda en la esquina superior derecha del cuadro delimitador, que por defecto se extiende de (0,0) a (1,1) en las coordenadas de los ejes (o en la notación del cuadro delimitador (x0,y0, width, height)=(0,0,1,1) ).

Para colocar la leyenda fuera del cuadro delimitador de ejes, se puede especificar una tupla (x0,y0) de coordenadas de ejes de la esquina inferior izquierda de la leyenda.

plt.legend(loc=(1.04,0))

Sin embargo, un enfoque más versátil sería especificar manualmente el cuadro delimitador en el que se debe colocar la leyenda, utilizando el argumento bbox_to_anchor . Uno puede restringirse para suministrar solo la parte (x0,y0) de bbox. Esto crea un cuadro de intervalo cero, desde el cual la leyenda se expandirá en la dirección dada por el argumento loc . P.ej

plt.legend(bbox_to_anchor=(1.04,1), loc="upper left")

coloca la leyenda fuera de los ejes, de modo que la esquina superior izquierda de la leyenda esté en la posición (1.04,1) en las coordenadas de los ejes.

Más abajo se dan ejemplos adicionales, donde además se muestra la interacción entre diferentes argumentos como el mode y ncols .

l1 = plt.legend(bbox_to_anchor=(1.04,1), borderaxespad=0) l2 = plt.legend(bbox_to_anchor=(1.04,0), loc="lower left", borderaxespad=0) l3 = plt.legend(bbox_to_anchor=(1.04,0.5), loc="center left", borderaxespad=0) l4 = plt.legend(bbox_to_anchor=(0,1.02,1,0.2), loc="lower left", mode="expand", borderaxespad=0, ncol=3) l5 = plt.legend(bbox_to_anchor=(1,0), loc="lower right", bbox_transform=fig.transFigure, ncol=3) l6 = plt.legend(bbox_to_anchor=(0.4,0.8), loc="upper right")

En esta pregunta se pueden encontrar detalles sobre cómo interpretar el argumento 4-tuple para bbox_to_anchor , como en l4 . El mode="expand" expande la leyenda horizontalmente dentro del cuadro delimitador dado por la 4-tupla. Para una leyenda expandida verticalmente, vea esta pregunta .

A veces puede ser útil especificar el cuadro delimitador en coordenadas de figura en lugar de coordenadas de ejes. Esto se muestra en el ejemplo l5 de arriba, donde se bbox_transform argumento bbox_transform para colocar la leyenda en la esquina inferior izquierda de la figura.

Postprocesamiento

La colocación de la leyenda fuera de los ejes a menudo conduce a la situación no deseada de que está total o parcialmente fuera del lienzo de la figura.

Las soluciones a este problema son:

  • Ajustar los parámetros de subplot
    Se pueden ajustar los parámetros de subplot de forma tal que los ejes ocupen menos espacio dentro de la figura (y, por lo tanto, dejen más espacio para la leyenda) utilizando plt.subplots_adjust . P.ej

    plt.subplots_adjust(right=0.7)

    deja un 30% de espacio en el lado derecho de la figura, donde se puede colocar la leyenda.

  • Diseño ajustado
    Uso de plt.tight_layout Permite ajustar automáticamente los parámetros de plt.tight_layout para que los elementos de la figura queden ajustados contra los bordes de la figura. Desafortunadamente, la leyenda no se tiene en cuenta en este automatismo, pero podemos proporcionar una caja rectangular en la que cabrá toda el área de subparcelas (incluidas las etiquetas).

    plt.tight_layout(rect=[0,0,0.75,1])

  • Guardando la figura con bbox_inches = "tight"
    El argumento bbox_inches = "tight" a plt.savefig se puede usar para guardar la figura de modo que todo el artista en el lienzo (incluida la leyenda) se ajuste al área guardada. Si es necesario, el tamaño de la figura se ajusta automáticamente.

    plt.savefig("output.png", bbox_inches="tight")

  • Ajustando automáticamente los parámetros de subplot
    En esta respuesta se puede encontrar una forma de ajustar automáticamente la posición de la subparcela para que la leyenda se ajuste dentro del lienzo sin cambiar el tamaño de la figura : Crear una figura con el tamaño exacto y sin relleno (y la leyenda fuera de los ejes)

Comparación entre los casos discutidos anteriormente:

Alternativas

Una figura leyenda
Uno puede usar una leyenda para la figura en lugar de los ejes, matplotlib.figure.Figure.legend . Esto se ha vuelto especialmente útil para la versión matplotlib> = 2.1, donde no se necesitan argumentos especiales

fig.legend(loc=7)

Para crear una leyenda para todos los artistas en los diferentes ejes de la figura. La leyenda se coloca utilizando el argumento loc , similar a cómo se coloca dentro de los ejes, pero en referencia a toda la figura, por lo tanto, estará fuera de los ejes de forma algo automática. Lo que queda es ajustar las subparcelas de modo que no haya superposición entre la leyenda y los ejes. Aquí el punto "Ajustar los parámetros de subplot" desde arriba será útil. Un ejemplo:

import numpy as np import matplotlib.pyplot as plt x = np.linspace(0,2*np.pi) colors=["#7aa0c4","#ca82e1" ,"#8bcd50","#e18882"] fig, axes = plt.subplots(ncols=2) for i in range(4): axes[i//2].plot(x,np.sin(x+i), color=colors[i],label="y=sin(x+{})".format(i)) fig.legend(loc=7) fig.tight_layout() fig.subplots_adjust(right=0.75) plt.show()

Leyenda dentro de ejes de subtrama dedicados
Una alternativa al uso de bbox_to_anchor sería colocar la leyenda en sus ejes de subtrama dedicados ( lax ). Dado que la subparcela de leyenda debe ser más pequeña que la gráfica, podemos usar gridspec_kw={"width_ratios":[4,1]} en la creación de los ejes. Podemos ocultar los ejes lax.axis("off") pero aún así colocar una leyenda. Los identificadores y las etiquetas de la leyenda deben obtenerse de la trama real mediante h,l = ax.get_legend_handles_labels() , y luego se pueden suministrar al leyenda en la subparcela lax , lax.legend(h,l) . Un ejemplo completo está abajo.

import matplotlib.pyplot as plt plt.rcParams["figure.figsize"] = 6,2 fig, (ax,lax) = plt.subplots(ncols=2, gridspec_kw={"width_ratios":[4,1]}) ax.plot(x,y, label="y=sin(x)") .... h,l = ax.get_legend_handles_labels() lax.legend(h,l, borderaxespad=0) lax.axis("off") plt.tight_layout() plt.show()

Esto produce una trama que es visualmente muy similar a la trama de arriba:

También podríamos usar los primeros ejes para colocar la leyenda, pero usar la bbox_transform de los ejes de leyenda,

ax.legend(bbox_to_anchor=(0,0,1,1), bbox_transform=lax.transAxes) lax.axis("off")

En este enfoque, no necesitamos obtener los bbox_to_anchor leyenda externamente, pero necesitamos especificar el argumento bbox_to_anchor .

Lecturas y notas adicionales:

  • Considere la guía de leyendas de matplotlib con algunos ejemplos de otras cosas que desea hacer con leyendas.
  • Se puede encontrar directamente algún código de ejemplo para colocar leyendas para gráficos circulares en respuesta a esta pregunta: Python - La leyenda se superpone con el gráfico circular
  • El argumento loc puede tomar números en lugar de cadenas, lo que acorta las llamadas, sin embargo, no se asignan de forma muy intuitiva entre sí. Aquí está el mapeo para referencia:

Tengo una serie de 20 parcelas (no subparcelas) que se realizarán en una sola figura. Quiero que la leyenda esté fuera de la caja. Al mismo tiempo, no quiero cambiar los ejes, ya que el tamaño de la figura se reduce. Por favor ayúdame para las siguientes consultas:

  1. Quiero mantener el cuadro de leyenda fuera del área de la trama. (Quiero que la leyenda esté afuera en el lado derecho del área de la parcela).
  2. ¿Existe de todos modos que reduzco el tamaño de fuente del texto dentro del cuadro de leyenda, de modo que el tamaño del cuadro de leyenda sea pequeño?

Además de todas las excelentes respuestas aquí, las versiones más recientes de matplotlib y pylab pueden determinar automáticamente dónde colocar la leyenda sin interferir con las parcelas .

pylab.legend(loc=''best'')

¡Esto colocará automáticamente la leyenda fuera de la trama!


Algo en estas líneas funcionó para mí. Comenzando con un poco de código tomado de Joe, este método modifica el ancho de la ventana para que se ajuste automáticamente a una leyenda a la derecha de la figura.

import matplotlib.pyplot as plt import numpy as np plt.ion() x = np.arange(10) fig = plt.figure() ax = plt.subplot(111) for i in xrange(5): ax.plot(x, i * x, label=''$y = %ix$''%i) # Put a legend to the right of the current axis leg = ax.legend(loc=''center left'', bbox_to_anchor=(1, 0.5)) plt.draw() # Get the ax dimensions. box = ax.get_position() xlocs = (box.x0,box.x1) ylocs = (box.y0,box.y1) # Get the figure size in inches and the dpi. w, h = fig.get_size_inches() dpi = fig.get_dpi() # Get the legend size, calculate new window width and change the figure size. legWidth = leg.get_window_extent().width winWidthNew = w*dpi+legWidth fig.set_size_inches(winWidthNew/dpi,h) # Adjust the window size to fit the figure. mgr = plt.get_current_fig_manager() mgr.window.wm_geometry("%ix%i"%(winWidthNew,mgr.window.winfo_height())) # Rescale the ax to keep its original size. factor = w*dpi/winWidthNew x0 = xlocs[0]*factor x1 = xlocs[1]*factor width = box.width*factor ax.set_position([x0,ylocs[0],x1-x0,ylocs[1]-ylocs[0]]) plt.draw()


Aquí hay otra solución, similar a la adición de bbox_extra_artists y bbox_inches , donde no tiene que tener sus artistas adicionales en el alcance de su llamada savefig . Se me ocurrió esto ya que genero la mayor parte de mi trama dentro de las funciones.

En lugar de agregar todas sus adiciones al cuadro delimitador cuando desee escribirlas, puede agregarlas con anticipación a los artistas de la Figure . Usando algo similar a la respuesta de Franck Dernoncourt arriba :

import matplotlib.pyplot as plt # data all_x = [10,20,30] all_y = [[1,3], [1.5,2.9],[3,2]] # plotting function def gen_plot(x, y): fig = plt.figure(1) ax = fig.add_subplot(111) ax.plot(all_x, all_y) lgd = ax.legend( [ "Lag " + str(lag) for lag in all_x], loc="center right", bbox_to_anchor=(1.3, 0.5)) fig.artists.append(lgd) # Here''s the change ax.set_title("Title") ax.set_xlabel("x label") ax.set_ylabel("y label") return fig # plotting fig = gen_plot(all_x, all_y) # No need for `bbox_extra_artists` fig.savefig("image_output.png", dpi=300, format="png", bbox_inches="tight")

Aquí está la trama generada.


Aquí hay un ejemplo del tutorial matplotlib que se encuentra aquí . Este es uno de los ejemplos más simples, pero agregué transparencia a la leyenda y agregué plt.show () para que pueda pegar esto en el shell interactivo y obtener un resultado:

import matplotlib.pyplot as plt p1, = plt.plot([1, 2, 3]) p2, = plt.plot([3, 2, 1]) p3, = plt.plot([2, 3, 1]) plt.legend([p2, p1, p3], ["line 1", "line 2", "line 3"]).get_frame().set_alpha(0.5) plt.show()


Como se ha señalado, también puede colocar la leyenda en la trama, o ligeramente desde el borde también. Aquí hay un ejemplo utilizando la API de Plotly Python , hecha con un cuaderno de IPython . Estoy en el equipo

Para empezar, querrás instalar los paquetes necesarios:

import plotly import math import random import numpy as np

Luego, instale Plotly:

un=''IPython.Demo'' k=''1fw3zw2o13'' py = plotly.plotly(username=un, key=k) def sin(x,n): sine = 0 for i in range(n): sign = (-1)**i sine = sine + ((x**(2.0*i+1))/math.factorial(2*i+1))*sign return sine x = np.arange(-12,12,0.1) anno = { ''text'': ''$//sum_{k=0}^{//infty} //frac {(-1)^k x^{1+2k}}{(1 + 2k)!}$'', ''x'': 0.3, ''y'': 0.6,''xref'': "paper", ''yref'': "paper",''showarrow'': False, ''font'':{''size'':24} } l = { ''annotations'': [anno], ''title'': ''Taylor series of sine'', ''xaxis'':{''ticks'':'''',''linecolor'':''white'',''showgrid'':False,''zeroline'':False}, ''yaxis'':{''ticks'':'''',''linecolor'':''white'',''showgrid'':False,''zeroline'':False}, ''legend'':{''font'':{''size'':16},''bordercolor'':''white'',''bgcolor'':''#fcfcfc''} } py.iplot([{''x'':x, ''y'':sin(x,1), ''line'':{''color'':''#e377c2''}, ''name'':''$x////$''},/ {''x'':x, ''y'':sin(x,2), ''line'':{''color'':''#7f7f7f''},''name'':''$ x-//frac{x^3}{6}$''},/ {''x'':x, ''y'':sin(x,3), ''line'':{''color'':''#bcbd22''},''name'':''$ x-//frac{x^3}{6}+//frac{x^5}{120}$''},/ {''x'':x, ''y'':sin(x,4), ''line'':{''color'':''#17becf''},''name'':''$ x-//frac{x^5}{120}$''}], layout=l)

Esto crea su gráfico y le brinda la oportunidad de mantener la leyenda dentro de la trama. El valor predeterminado para la leyenda, si no está configurado, es colocarlo en el gráfico, como se muestra aquí.

Para una ubicación alternativa, puede alinear estrechamente el borde del gráfico y el borde de la leyenda, y eliminar las líneas del borde para un ajuste más estrecho.

Puede mover y cambiar el estilo de la leyenda y el gráfico con código, o con la GUI. Para cambiar la leyenda, tiene las siguientes opciones para ubicar la leyenda dentro del gráfico asignando valores de x e y de <= 1. Por ejemplo:

  • {"x" : 0,"y" : 0} - Abajo a la izquierda
  • {"x" : 1, "y" : 0} - Abajo a la derecha
  • {"x" : 1, "y" : 1} - Arriba a la derecha
  • {"x" : 0, "y" : 1} - Arriba a la izquierda
  • {"x" :.5, "y" : 0} - Centro inferior
  • {"x": .5, "y" : 1} - Centro superior

En este caso, elegimos la parte superior derecha, estilo de legendstyle = {"x" : 1, "y" : 1} , también descrita en la documentación :


Crear propiedades de fuente

from matplotlib.font_manager import FontProperties fontP = FontProperties() fontP.set_size(''small'') legend([plot1], "title", prop=fontP)


Hay varias formas de hacer lo que quieres. Para agregar a lo que @inalis y @Navi ya dijeron, puede usar el argumento de la palabra clave bbox_to_anchor para colocar la leyenda parcialmente fuera de los ejes y / o reducir el tamaño de la fuente.

Antes de considerar reducir el tamaño de la fuente (lo que puede hacer que las cosas sean muy difíciles de leer), intente jugar y colocar la leyenda en diferentes lugares:

Entonces, comencemos con un ejemplo genérico:

import matplotlib.pyplot as plt import numpy as np x = np.arange(10) fig = plt.figure() ax = plt.subplot(111) for i in xrange(5): ax.plot(x, i * x, label=''$y = %ix$'' % i) ax.legend() plt.show()

Si hacemos lo mismo, pero si usamos el argumento de la palabra clave bbox_to_anchor , podemos cambiar la leyenda ligeramente fuera de los límites de los ejes:

import matplotlib.pyplot as plt import numpy as np x = np.arange(10) fig = plt.figure() ax = plt.subplot(111) for i in xrange(5): ax.plot(x, i * x, label=''$y = %ix$'' % i) ax.legend(bbox_to_anchor=(1.1, 1.05)) plt.show()

Del mismo modo, puede hacer que la leyenda sea más horizontal y / o ponerla en la parte superior de la figura (también estoy activando esquinas redondeadas y una sombra paralela simple):

import matplotlib.pyplot as plt import numpy as np x = np.arange(10) fig = plt.figure() ax = plt.subplot(111) for i in xrange(5): line, = ax.plot(x, i * x, label=''$y = %ix$''%i) ax.legend(loc=''upper center'', bbox_to_anchor=(0.5, 1.05), ncol=3, fancybox=True, shadow=True) plt.show()

Alternativamente, puede reducir el ancho de la trama actual y colocar la leyenda completamente fuera del eje de la figura:

import matplotlib.pyplot as plt import numpy as np x = np.arange(10) fig = plt.figure() ax = plt.subplot(111) for i in xrange(5): ax.plot(x, i * x, label=''$y = %ix$''%i) # Shrink current axis by 20% box = ax.get_position() ax.set_position([box.x0, box.y0, box.width * 0.8, box.height]) # Put a legend to the right of the current axis ax.legend(loc=''center left'', bbox_to_anchor=(1, 0.5)) plt.show()

Y de una manera similar, puede reducir la trama verticalmente y colocar una leyenda horizontal en la parte inferior:

import matplotlib.pyplot as plt import numpy as np x = np.arange(10) fig = plt.figure() ax = plt.subplot(111) for i in xrange(5): line, = ax.plot(x, i * x, label=''$y = %ix$''%i) # Shrink current axis''s height by 10% on the bottom box = ax.get_position() ax.set_position([box.x0, box.y0 + box.height * 0.1, box.width, box.height * 0.9]) # Put a legend below current axis ax.legend(loc=''upper center'', bbox_to_anchor=(0.5, -0.05), fancybox=True, shadow=True, ncol=5) plt.show()

Echa un vistazo a la guía de leyendas de matplotlib . También puede echar un vistazo a plt.figlegend() . Espero que ayude un poco, de todos modos!


La solución que me funcionó cuando tuve una gran leyenda fue usar un diseño de imagen extra vacío. En el siguiente ejemplo, hice 4 filas y en la parte inferior trazo la imagen con el desplazamiento de la leyenda (bbox_to_anchor) en la parte superior, no se corta.

f = plt.figure() ax = f.add_subplot(414) lgd = ax.legend(loc=''upper left'', bbox_to_anchor=(0, 4), mode="expand", borderaxespad=0.3) ax.autoscale_view() plt.savefig(fig_name, format=''svg'', dpi=1200, bbox_extra_artists=(lgd,), bbox_inches=''tight'')


No es exactamente lo que pediste, pero encontré que es una alternativa para el mismo problema. Haz la leyenda semi-transparente, así:

Haga esto con:

fig = pylab.figure() ax = fig.add_subplot(111) ax.plot(x,y,label=label,color=color) # Make the legend transparent: ax.legend(loc=2,fontsize=10,fancybox=True).get_frame().set_alpha(0.5) # Make a transparent text box ax.text(0.02,0.02,yourstring, verticalalignment=''bottom'', horizontalalignment=''left'', fontsize=10, bbox={''facecolor'':''white'', ''alpha'':0.6, ''pad'':10}, transform=self.ax.transAxes)


No sé si ya resolvió su problema ... probablemente sí, pero ... Simplemente usé la cadena ''afuera'' para la ubicación, como en Matlab. He importado pylab desde matplotlib. ver el código de la siguiente manera:

from matplotlib as plt from matplotlib.font_manager import FontProperties ... ... t = A[:,0] sensors = A[:,index_lst] for i in range(sensors.shape[1]): plt.plot(t,sensors[:,i]) plt.xlabel(''s'') plt.ylabel(''°C'') lgd = plt.legend(b,loc=''center left'', bbox_to_anchor=(1, 0.5),fancybox = True, shadow = True)

Pincha para ver la trama.


Para colocar la leyenda fuera del área de trazado, use las palabras clave loc y bbox_to_anchor de la leyenda (). Por ejemplo, el siguiente código colocará la leyenda a la derecha del área de trazado:

legend(loc="upper left", bbox_to_anchor=(1,1))

Para más información, consulte la guía de leyenda.


Respuesta corta: puedes usar bbox_to_anchor + bbox_extra_artists + bbox_inches=''tight'' .

Respuesta más larga: puede usar bbox_to_anchor para especificar manualmente la ubicación del cuadro de leyenda, como han señalado otras personas en las respuestas.

Sin embargo, el problema habitual es que el cuadro de leyenda está recortado, por ejemplo:

import matplotlib.pyplot as plt # data all_x = [10,20,30] all_y = [[1,3], [1.5,2.9],[3,2]] # Plot fig = plt.figure(1) ax = fig.add_subplot(111) ax.plot(all_x, all_y) # Add legend, title and axis labels lgd = ax.legend( [ ''Lag '' + str(lag) for lag in all_x], loc=''center right'', bbox_to_anchor=(1.3, 0.5)) ax.set_title(''Title'') ax.set_xlabel(''x label'') ax.set_ylabel(''y label'') fig.savefig(''image_output.png'', dpi=300, format=''png'')

Para evitar que el cuadro de leyenda se recorte, cuando guarde la figura, puede usar los parámetros bbox_extra_artists y bbox_inches para pedir a savefig que incluya elementos recortados en la imagen guardada:

fig.savefig(''image_output.png'', bbox_extra_artists=(lgd,), bbox_inches=''tight'')

Ejemplo (solo cambié la última línea para agregar 2 parámetros a fig.savefig() ):

import matplotlib.pyplot as plt # data all_x = [10,20,30] all_y = [[1,3], [1.5,2.9],[3,2]] # Plot fig = plt.figure(1) ax = fig.add_subplot(111) ax.plot(all_x, all_y) # Add legend, title and axis labels lgd = ax.legend( [ ''Lag '' + str(lag) for lag in all_x], loc=''center right'', bbox_to_anchor=(1.3, 0.5)) ax.set_title(''Title'') ax.set_xlabel(''x label'') ax.set_ylabel(''y label'') fig.savefig(''image_output.png'', dpi=300, format=''png'', bbox_extra_artists=(lgd,), bbox_inches=''tight'')

Deseo que matplotlib permita de forma nativa la ubicación externa para el cuadro de leyenda como lo hace Matlab :

figure x = 0:.2:12; plot(x,besselj(1,x),x,besselj(2,x),x,besselj(3,x)); hleg = legend(''First'',''Second'',''Third'',... ''Location'',''NorthEastOutside'') % Make the text of the legend italic and color it brown set(hleg,''FontAngle'',''italic'',''TextColor'',[.3,.2,.1])


Simplemente llame a legend() llame después de la plot() llame así:

# matplotlib plt.plot(...) plt.legend(loc=''center left'', bbox_to_anchor=(1, 0.5)) # Pandas df.myCol.plot().legend(loc=''center left'', bbox_to_anchor=(1, 0.5))

Los resultados se verían algo como esto:


También puedes probar figlegend . Es posible crear una leyenda independiente de cualquier objeto Axes. Sin embargo, es posible que deba crear algunas rutas "ficticias" para asegurarse de que el formato de los objetos se transmita correctamente.


Respuesta corta : invoca la opción de arrastrar en la leyenda y muévela interactivamente donde quieras:

ax.legend().draggable()

Respuesta larga : si prefiere colocar la leyenda de forma interactiva / manual en lugar de programada, puede alternar el modo de la leyenda que se puede arrastrar para que pueda arrastrarla a donde desee. Revisa el siguiente ejemplo:

import matplotlib.pylab as plt import numpy as np #define the figure and get an axes instance fig = plt.figure() ax = fig.add_subplot(111) #plot the data x = np.arange(-5, 6) ax.plot(x, x*x, label=''y = x^2'') ax.plot(x, x*x*x, label=''y = x^3'') ax.legend().draggable() plt.show()