with outside found example python matplotlib legend

outside - python legend()



Mover la leyenda matplotlib fuera del eje hace que se corte por el cuadro de la figura (3)

Aquí hay otra solución muy manual. Puede definir el tamaño del eje y las separaciones se consideran en consecuencia (incluida la leyenda y las marcas). Espero que sea útil para alguien.

Ejemplo (el tamaño de los ejes es el mismo!):

Código:

#================================================== # Plot table colmap = [(0,0,1) #blue ,(1,0,0) #red ,(0,1,0) #green ,(1,1,0) #yellow ,(1,0,1) #magenta ,(1,0.5,0.5) #pink ,(0.5,0.5,0.5) #gray ,(0.5,0,0) #brown ,(1,0.5,0) #orange ] import matplotlib.pyplot as plt import numpy as np import collections df = collections.OrderedDict() df[''labels''] = [''GWP100a/n[kgCO2eq]/n/nasedf/nasdf/nadfs'',''human/n[pts]'',''ressource/n[pts]''] df[''all-petroleum long name''] = [3,5,2] df[''all-electric''] = [5.5, 1, 3] df[''HEV''] = [3.5, 2, 1] df[''PHEV''] = [3.5, 2, 1] numLabels = len(df.values()[0]) numItems = len(df)-1 posX = np.arange(numLabels)+1 width = 1.0/(numItems+1) fig = plt.figure(figsize=(2,2)) ax = fig.add_subplot(111) for iiItem in range(1,numItems+1): ax.bar(posX+(iiItem-1)*width, df.values()[iiItem], width, color=colmap[iiItem-1], label=df.keys()[iiItem]) ax.set(xticks=posX+width*(0.5*numItems), xticklabels=df[''labels'']) #-------------------------------------------------- # Change padding and margins, insert legend fig.tight_layout() #tight margins leg = ax.legend(loc=''upper left'', bbox_to_anchor=(1.02, 1), borderaxespad=0) plt.draw() #to know size of legend padLeft = ax.get_position().x0 * fig.get_size_inches()[0] padBottom = ax.get_position().y0 * fig.get_size_inches()[1] padTop = ( 1 - ax.get_position().y0 - ax.get_position().height ) * fig.get_size_inches()[1] padRight = ( 1 - ax.get_position().x0 - ax.get_position().width ) * fig.get_size_inches()[0] dpi = fig.get_dpi() padLegend = ax.get_legend().get_frame().get_width() / dpi widthAx = 3 #inches heightAx = 3 #inches widthTot = widthAx+padLeft+padRight+padLegend heightTot = heightAx+padTop+padBottom # resize ipython window (optional) posScreenX = 1366/2-10 #pixel posScreenY = 0 #pixel canvasPadding = 6 #pixel canvasBottom = 40 #pixel ipythonWindowSize = ''{0}x{1}+{2}+{3}''.format(int(round(widthTot*dpi))+2*canvasPadding ,int(round(heightTot*dpi))+2*canvasPadding+canvasBottom ,posScreenX,posScreenY) fig.canvas._tkcanvas.master.geometry(ipythonWindowSize) plt.draw() #to resize ipython window. Has to be done BEFORE figure resizing! # set figure size and ax position fig.set_size_inches(widthTot,heightTot) ax.set_position([padLeft/widthTot, padBottom/heightTot, widthAx/widthTot, heightAx/heightTot]) plt.draw() plt.show() #-------------------------------------------------- #==================================================

Estoy familiarizado con las siguientes preguntas:

Matplotlib savefig con una leyenda fuera de la trama

Cómo sacar la leyenda de la trama

Parece que las respuestas en estas preguntas tienen el lujo de ser capaces de jugar con la contracción exacta del eje para que la leyenda se adapte.

La reducción de los ejes, sin embargo, no es una solución ideal porque reduce los datos y hace que sea más difícil de interpretar; particularmente cuando es complejo y hay muchas cosas sucediendo ... por lo tanto, necesita una gran leyenda

El ejemplo de una leyenda compleja en la documentación demuestra la necesidad de esto porque la leyenda en su trazado realmente oculta por completo múltiples puntos de datos.

http://matplotlib.sourceforge.net/users/legend_guide.html#legend-of-complex-plots

Lo que me gustaría poder hacer es expandir dinámicamente el tamaño del cuadro de figura para acomodar la leyenda de la figura en expansión.

import matplotlib.pyplot as plt import numpy as np x = np.arange(-2*np.pi, 2*np.pi, 0.1) fig = plt.figure(1) ax = fig.add_subplot(111) ax.plot(x, np.sin(x), label=''Sine'') ax.plot(x, np.cos(x), label=''Cosine'') ax.plot(x, np.arctan(x), label=''Inverse tan'') lgd = ax.legend(loc=9, bbox_to_anchor=(0.5,0)) ax.grid(''on'')

Observe cómo la etiqueta final ''Tanto inverso'' está realmente fuera del cuadro de figura (y se ve mal recortada, ¡no la calidad de publicación!)

Finalmente, me han dicho que este es un comportamiento normal en R y LaTeX, así que estoy un poco confundido por qué esto es tan difícil en Python ... ¿Hay alguna razón histórica? ¿Matlab es igualmente pobre en este asunto?

Tengo la versión (un poco) más larga de este código en pastebin http://pastebin.com/grVjc007


Lo siento EMS, pero en realidad acabo de recibir otra respuesta de la lista mailling matplotlib (Gracias a Benjamin Root).

El código que estoy buscando es ajustar la llamada a savefig a:

fig.savefig(''samplefigure'', bbox_extra_artists=(lgd,), bbox_inches=''tight'') #Note that the bbox_extra_artists must be an iterable

Esto es aparentemente similar a llamar a tight_layout, pero en su lugar, permite que savefig considere artistas adicionales en el cálculo. De hecho, esto redimensionó el cuadro de figuras según lo deseado.

import matplotlib.pyplot as plt import numpy as np x = np.arange(-2*np.pi, 2*np.pi, 0.1) fig = plt.figure(1) ax = fig.add_subplot(111) ax.plot(x, np.sin(x), label=''Sine'') ax.plot(x, np.cos(x), label=''Cosine'') ax.plot(x, np.arctan(x), label=''Inverse tan'') handles, labels = ax.get_legend_handles_labels() lgd = ax.legend(handles, labels, loc=''upper center'', bbox_to_anchor=(0.5,-0.1)) ax.grid(''on'') fig.savefig(''samplefigure'', bbox_extra_artists=(lgd,), bbox_inches=''tight'')

Esto produce:


Agregué: Encontré algo que debería funcionar de inmediato, pero el resto del código a continuación también ofrece una alternativa.

Use la función subplots_adjust() para mover la parte inferior de la subtrama hacia arriba:

fig.subplots_adjust(bottom=0.2) # <-- Change the 0.02 to work for your plot.

Luego juegue con el desplazamiento en la leyenda bbox_to_anchor parte del comando de leyenda, para obtener el cuadro de leyenda donde lo desee. Alguna combinación de configuración del figsize y el uso de figsize subplots_adjust(bottom=...) debería producir un diagrama de calidad para usted.

Alternativa: simplemente cambié la línea:

fig = plt.figure(1)

a:

fig = plt.figure(num=1, figsize=(13, 13), dpi=80, facecolor=''w'', edgecolor=''k'')

y cambiado

lgd = ax.legend(loc=9, bbox_to_anchor=(0.5,0))

a

lgd = ax.legend(loc=9, bbox_to_anchor=(0.5,-0.02))

y aparece bien en mi pantalla (un monitor CRT de 24 pulgadas).

Aquí figsize=(M,N) establece que la ventana de la figura sea M pulgadas por N pulgadas. Solo juega con esto hasta que te quede bien. Conviértalo en un formato de imagen más escalable y use GIMP para editar si es necesario, o simplemente recorte con la opción de viewport gráfica LaTeX cuando incluya gráficos.