2012-03-23 40 views
72

Estoy trazando el mismo tipo de información, pero para diferentes países, con múltiples subtramas con matplotlib. Es decir, tengo 9 tramas en una cuadrícula de 3x3, todas con lo mismo para las líneas (por supuesto, diferentes valores por línea).¿cómo hago una sola leyenda para muchas subtramas con matplotlib?

Sin embargo, no he descubierto cómo poner una sola leyenda (ya que las 9 subtramas tienen las mismas líneas) en la figura solo una vez.

¿Cómo puedo hacer eso?

Respuesta

68

figlegend puede ser lo que está buscando: http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.figlegend

Ejemplo aquí: http://matplotlib.org/examples/pylab_examples/figlegend_demo.html

Otro ejemplo:

plt.figlegend(lines, labels, loc = 'lower center', ncol=5, labelspacing=0.) 

o:

fig.legend(lines, labels, loc = (0.5, 0), ncol=5) 
+1

Conozco las líneas que quiero poner en la leyenda, pero ¿cómo obtengo la variable 'lines' para ponerla en el argumento de' legend'? –

+1

@patapouf_ai 'lines' es una lista de resultados que se devuelven de' axes.plot() '(es decir, cada' axes.plot' o rutina similar devuelve una "línea"). Ver también el ejemplo vinculado. – Evert

13

Sólo hay que pregunta por la leyenda una vez, fuera de tu loop.

Por ejemplo, en este caso tengo 4 subtramas, con las mismas líneas, y una sola leyenda.

from matplotlib.pyplot import * 

ficheiros = ['120318.nc', '120319.nc', '120320.nc', '120321.nc'] 

fig = figure() 
fig.suptitle('concentration profile analysis') 

for a in range(len(ficheiros)): 
    # dados is here defined 
    level = dados.variables['level'][:] 

    ax = fig.add_subplot(2,2,a+1) 
    xticks(range(8), ['0h','3h','6h','9h','12h','15h','18h','21h']) 
    ax.set_xlabel('time (hours)') 
    ax.set_ylabel('CONC ($\mu g. m^{-3}$)') 

    for index in range(len(level)): 
     conc = dados.variables['CONC'][4:12,index] * 1e9 
     ax.plot(conc,label=str(level[index])+'m') 

    dados.close() 

ax.legend(bbox_to_anchor=(1.05, 0), loc='lower left', borderaxespad=0.) 
     # it will place the legend on the outer right-hand side of the last axes 

show() 
+3

'figlegend', como es sugerido por Evert, parece ser una solución mucho mejor;) – carla

+10

el problema de' fig.legend() 'es que requiere identificación para todas las líneas (gráficos) ... como, para cada subparcela , Estoy usando un bucle para generar las líneas, la única solución que descubrí para superar esto es crear una lista vacía antes del segundo ciclo, y luego agregar las líneas a medida que se crean ... Entonces uso esta lista como un argumento para la función 'fig.legend()'. – carla

+0

Una pregunta similar [aquí] (https://stackoverflow.com/questions/22001756/one-legend-for-all-subplots-in-pyplot) –

12

Para la colocación automática de una sola leyenda en un figure con muchos ejes, como los obtenidos con subplots(), la siguiente solución funciona muy bien:

plt.legend(lines, labels, loc = 'lower center', bbox_to_anchor = (0,-0.1,1,1), 
      bbox_transform = plt.gcf().transFigure) 

Con bbox_to_anchor y bbox_transform=plt.gcf().transFigure está definiendo una nuevo cuadro delimitador del tamaño de su figure como referencia para loc. El uso de (0,-0.1,1,1) mueve esta caja de dibujo ligeramente hacia abajo para evitar que la leyenda se coloque sobre otros artistas.

OBS: utilizar esta solución después de que utiliza fig.set_size_inches() y antes del uso fig.tight_layout()

+1

O simpy 'loc = 'centro superior', bbox_to_anchor = (0.5, 0), bbox_transform = plt.gcf(). TransFigure' y no se superpondrá con seguridad. –

+1

Todavía no estoy seguro de por qué, pero la solución de Evert no funcionó para mí, la leyenda siguió siendo cortada. Esta solución (junto con el comentario de davor) funcionó muy limpiamente: la leyenda se colocó como se esperaba y completamente visible. ¡Gracias! –

7

También hay una función agradable get_legend_handles_labels() puede llamar en el último eje (si iterar sobre ellos) que sería recoger todo lo que necesita de label= argumentos:

handles, labels = ax.get_legend_handles_labels() 
fig.legend(handles, labels, loc='upper center') 
+1

Esta debería ser la respuesta principal. – naught101

0

Esta respuesta es un complemento a @ Evert está en la posición de la leyenda.

Mi primera solución try @ Evert falló debido a la superposición de la leyenda y el título de la subtrama.

De hecho, las superposiciones son causadas por fig.tight_layout(), que cambia el diseño de las subtramas sin tener en cuenta la leyenda de la figura. Sin embargo, es necesario fig.tight_layout().

Para evitar las superposiciones, podemos decir fig.tight_layout() para dejar espacios para la leyenda de la figura por fig.tight_layout(rect=(0,0,1,0.9)).

Description of tight_layout() parameters.

Cuestiones relacionadas