Matplotlib - legenda global e subtramas à parte do título

125

Comecei com matplot e gerenciei alguns gráficos básicos, mas agora acho difícil descobrir como fazer algumas coisas que preciso agora :(

Minha pergunta real é como colocar um título global e uma legenda global em uma figura com subtramas.

Estou fazendo subplots 2x3, onde tenho muitos gráficos diferentes em várias cores (cerca de 200). Para distinguir (a maioria) deles, escrevi 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

(alguma ideia sobre isso? :)) Cada subtrama tem a mesma função de estilo.

Agora estou tentando obter um título global para todos os subenredos e também uma legenda global que explica todos os estilos. Também preciso fazer a fonte pequena para caber em todos os 200 estilos lá (não preciso de estilos completamente únicos, mas pelo menos alguma tentativa)

Alguém pode me ajudar a resolver essa tarefa?

Gerenuk
fonte

Respostas:

192

Título global : Em versões mais recentes de matplotlib, pode-se usar o método Figure.suptitle () de Figure:

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

Alternativamente (com base no comentário de @Steven C. Howell abaixo (obrigado!)), Use a função matplotlib.pyplot.suptitle () :

 import matplotlib.pyplot as plt
 # plot stuff
 # ...
 plt.suptitle("Title centered above all subplots", fontsize=14)
orbeckst
fonte
64
Para quem está importando assim:, import matplotlib.pyplot as plto comando pode ser digitado simplesmente como plt.figure(); plt.suptitle('Title centered above all subplots'); plt.subplot(231); plt.plot(data[:,0], data[:,1]);etc ...
Steven C. Howell
1
Obrigado. Esta deve ser a resposta real selecionada.
gustafbstrom
62

Além da resposta orbeckst, pode-se também querer deslocar as subtramas para baixo. Aqui está um MWE no 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")

dá:

insira a descrição da imagem aqui

Adobe
fonte
2
esta deve ser a melhor resposta
Statham
Acordado ! A resposta aceita introduz outra dependência, portanto, não responde adequadamente à pergunta do OP.
Yohan Obadia
7

Para rótulos de legenda pode usar algo como abaixo. Legendlabels são as linhas de plotagem salvas. modFreq é onde o nome dos rótulos reais correspondentes às linhas do gráfico. Então, o terceiro parâmetro é a localização da legenda. Por último, você pode passar qualquer argumento como eu fiz aqui, mas principalmente precisa dos três primeiros. Além disso, você deve fazer isso se definir os rótulos corretamente no comando de plotagem. Basta chamar a legenda com o parâmetro de localização e encontrar os rótulos em cada uma das linhas. Tive mais sorte fazendo minha própria lenda como abaixo. Parece funcionar em todos os casos em que nunca pareceu funcionar corretamente de outra forma. Se você não entender, me avise:

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)

Você também pode usar a perna para alterar o tamanho da fonte ou quase qualquer parâmetro da legenda.

O título global, conforme declarado no comentário acima, pode ser feito com a adição de texto de acordo com o link fornecido: 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
fonte
4

suptitleparece o caminho a seguir, mas vale a pena, o figuretem uma transFigurepropriedade que você pode usar:

fig=figure(1)
text(0.5, 0.95, 'test', transform=fig.transFigure, horizontalalignment='center')
matemática
fonte