¿Cómo hago una sola leyenda para muchas subplots con matplotlib?

Estoy trazando el mismo tipo de información, pero para diferentes países, con múltiples subplots con matplotlib. Es decir, tengo 9 gráficos en una cuadrícula de 3×3, todos con el mismo para líneas (por supuesto, diferentes valores por línea).

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

¿Cómo puedo hacer eso?

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 ) 

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

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

Solo tienes que pedir la leyenda una vez, fuera de tu bucle.

Por ejemplo, en este caso tengo 4 subplots, 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() 

Para el posicionamiento automático de una sola leyenda en una figure con muchos ejes, como los obtenidos con subplots() , la siguiente solución funciona realmente 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 un nuevo cuadro de límite del tamaño de su figure para que sea una referencia para loc . El uso de (0,-0.1,1,1) mueve este cuadro de buzón ligeramente hacia abajo para evitar que la leyenda se coloque sobre otros artistas.

OBS: use esta solución DESPUÉS de usar fig.set_size_inches() y ANTES de usar fig.tight_layout()

Aunque es bastante tarde para el juego, daré otra solución aquí, ya que este es uno de los primeros enlaces que aparecen en Google. Usando matplotlib 2.2.2, esto se puede lograr usando la característica gridspec. En el siguiente ejemplo, el objective es tener cuatro subplots organizadas de forma 2×2 con la leyenda mostrada en la parte inferior. Se crea un eje ‘falso’ en la parte inferior para colocar la leyenda en un lugar fijo. El eje ‘falso’ se desactiva, por lo que solo se muestra la leyenda. Resultado: http://sofes.miximages.com/python/5LUWM.png .

 import matplotlib.pyplot as plt import matplotlib.gridspec as gridspec #Gridspec demo fig = plt.figure() fig.set_size_inches(8,9) fig.set_dpi(100) rows = 17 #the larger the number here, the smaller the spacing around the legend start1 = 0 end1 = int((rows-1)/2) start2 = end1 end2 = int(rows-1) gspec = gridspec.GridSpec(ncols=4, nrows=rows) axes = [] axes.append(fig.add_subplot(gspec[start1:end1,0:2])) axes.append(fig.add_subplot(gspec[start2:end2,0:2])) axes.append(fig.add_subplot(gspec[start1:end1,2:4])) axes.append(fig.add_subplot(gspec[start2:end2,2:4])) axes.append(fig.add_subplot(gspec[end2,0:4])) line, = axes[0].plot([0,1],[0,1],'b') #add some data axes[-1].legend((line,),('Test',),loc='center') #create legend on bottommost axis axes[-1].set_axis_off() #don't show bottommost axis fig.tight_layout() plt.show() 

Esta respuesta es un complemento de @ Evert’s en la posición de leyenda.

Mi primer bash en la solución de @ Evert falló debido a la superposición de la leyenda y el título de la ttwig secundaria.

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

Para evitar las superposiciones, podemos indicarle a fig.tight_layout() que deje espacios para la leyenda de la figura mediante fig.tight_layout(rect=(0,0,1,0.9)) .

Descripción de los parámetros de tight_layout () .