Matplotlib - subtramas de leyenda global y título aparte

125

Comencé con matplot y manejé algunos gráficos básicos, pero ahora me resulta difícil descubrir cómo hacer algunas cosas que necesito ahora :(

Mi pregunta real es cómo colocar un título global y una leyenda global en una figura con subtramas.

Estoy haciendo subtramas 2x3 donde tengo muchos gráficos diferentes en varios colores (alrededor de 200). Para distinguir (la mayoría) de ellos escribí algo como

def style(i, total):
    return dict(color=jet(i/total),
                linestyle=["-", "--", "-.", ":"][i%4],
                marker=["+", "*", "1", "2", "3", "4", "s"][i%7])

fig=plt.figure()
p0=fig.add_subplot(321)
for i, y in enumerate(data):
    p0.plot(x, trans0(y), "-", label=i, **style(i, total))
# and more subplots with other transN functions

(¿Alguna idea sobre esto? :)) Cada subtrama tiene la misma función de estilo.

Ahora estoy tratando de obtener un título global para todas las subtramas y también una leyenda global que explique todos los estilos. También necesito hacer que la fuente sea pequeña para que se ajuste a los 200 estilos allí (no necesito estilos completamente únicos, pero al menos algún intento)

¿Alguien puede ayudarme a resolver esta tarea?

Gerenuk
fuente

Respuestas:

192

Título global : en las versiones más recientes de matplotlib, se puede usar el método Figure.suptitle () de Figure:

import matplotlib.pyplot as plt
fig = plt.gcf()
fig.suptitle("Title centered above all subplots", fontsize=14)

Alternativamente (basado en el comentario de @Steven C. Howell a continuación (¡gracias!)), Use la función matplotlib.pyplot.suptitle () :

 import matplotlib.pyplot as plt
 # plot stuff
 # ...
 plt.suptitle("Title centered above all subplots", fontsize=14)
orbeckst
fuente
64
Para aquellos que importan así:, import matplotlib.pyplot as pltel comando podría ingresarse simplemente como plt.figure(); plt.suptitle('Title centered above all subplots'); plt.subplot(231); plt.plot(data[:,0], data[:,1]);etc ...
Steven C. Howell
1
Gracias. Esta debería ser la respuesta seleccionada real.
gustafbstrom
62

Además de la respuesta de orbeckst, es posible que también desee cambiar las subtramas hacia abajo. Aquí hay un MWE en estilo OOP:

import matplotlib.pyplot as plt

fig = plt.figure()
st = fig.suptitle("suptitle", fontsize="x-large")

ax1 = fig.add_subplot(311)
ax1.plot([1,2,3])
ax1.set_title("ax1")

ax2 = fig.add_subplot(312)
ax2.plot([1,2,3])
ax2.set_title("ax2")

ax3 = fig.add_subplot(313)
ax3.plot([1,2,3])
ax3.set_title("ax3")

fig.tight_layout()

# shift subplots down:
st.set_y(0.95)
fig.subplots_adjust(top=0.85)

fig.savefig("test.png")

da:

ingrese la descripción de la imagen aquí

Adobe
fuente
2
esta debería ser la mejor respuesta
Statham
¡De acuerdo! La respuesta aceptada introduce otra dependencia, por lo tanto, no responde adecuadamente a la pregunta OP.
Yohan Obadia
7

Para las etiquetas de leyenda, puede usar algo como a continuación. Las etiquetas de leyenda son las líneas de trama guardadas. modFreq es donde el nombre de las etiquetas reales correspondientes a las líneas de la trama. Luego, el tercer parámetro es la ubicación de la leyenda. Por último, puede pasar cualquier argumento como lo he hecho aquí, pero principalmente necesito los tres primeros. Además, se supone que debe hacerlo si establece las etiquetas correctamente en el comando de trazado. Simplemente llame a la leyenda con el parámetro de ubicación y encuentre las etiquetas en cada una de las líneas. He tenido más suerte haciendo mi propia leyenda como se muestra a continuación. Parece funcionar en todos los casos en los que nunca pareció haber hecho lo contrario. Si no entiende, avíseme:

legendLabels = []
for i in range(modSize):
    legendLabels.append(ax.plot(x,hstack((array([0]),actSum[j,semi,i,semi])), color=plotColor[i%8], dashes=dashes[i%4])[0]) #linestyle=dashs[i%4]       
legArgs = dict(title='AM Templates (Hz)',bbox_to_anchor=[.4,1.05],borderpad=0.1,labelspacing=0,handlelength=1.8,handletextpad=0.05,frameon=False,ncol=4, columnspacing=0.02) #ncol,numpoints,columnspacing,title,bbox_transform,prop
leg = ax.legend(tuple(legendLabels),tuple(modFreq),'upper center',**legArgs)
leg.get_title().set_fontsize(tick_size)

También puede usar la pierna para cambiar el tamaño de fuente o casi cualquier parámetro de la leyenda.

El título global como se indica en el comentario anterior se puede hacer agregando texto según el enlace proporcionado: http://matplotlib.sourceforge.net/examples/pylab_examples/newscalarformatter_demo.html

f.text(0.5,0.975,'The new formatter, default settings',horizontalalignment='center',
       verticalalignment='top')
J Spen
fuente
4

suptitleparece el camino a seguir, pero por lo que vale, figuretiene una transFigurepropiedad que puede usar:

fig=figure(1)
text(0.5, 0.95, 'test', transform=fig.transFigure, horizontalalignment='center')
Mathtick
fuente