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.