2012-03-23 80 views
72

我正在繪製相同類型的信息,但對於不同的國家,多個子圖與matplotlib。也就是說,我在一個3x3網格上有9個圖,所有線都有相同的值(當然,每行的值不同)。如何使用matplotlib爲許多subplots製作單個圖例?

但是,我還沒有想出如何將一個圖例(因爲所有9個子圖都有相同的行)放在一個圖上。

我該怎麼做?

回答

68

figlegend可能是你在找什麼:http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.figlegend

這裏舉例:http://matplotlib.org/examples/pylab_examples/figlegend_demo.html

又如:

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

或:

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

我知道我想要放在圖例中的幾行,但是如何獲得'lines'變量來放入'legend'的參數呢? – 2017-04-10 12:51:58

+1

@patapouf_ai'lines'是從'axes.plot()'返回的結果列表(即每個'axes.plot'或類似的例程返回一個「行」)。另請參閱鏈接的示例。 – Evert 2017-04-10 20:13:46

13

你只需要在你的循環之外請求傳說一次。

例如,在這種情況下,我有4個子圖,具有相同的線條和一個圖例。

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',如Evert所要求的,似乎是一個更好的解決方案;) – carla 2012-03-23 11:06:13

+10

'fig.legend()'的問題是它需要對所有線(圖)進行識別......對於每個子圖,我正在使用一個循環來生成這些行,唯一能解決這個問題的方案是在第二個循環之前創建一個空列表,然後在創建行時添加這些行......然後我使用這個列表作爲對'fig.legend()'函數的一個參數。 – carla 2012-03-23 12:06:30

+0

類似的問題[這裏](https://stackoverflow.com/questions/22001756/one-legend-for-all-subplots-in-pyplot) – 2017-08-02 07:34:52

12

對於單個傳說在figure自動定位與許多軸,就像subplots()獲得的,下面的解決方案工作得很好:

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

隨着bbox_to_anchorbbox_transform=plt.gcf().transFigure要定義將您的figure大小的新邊界框作爲loc的參考。使用(0,-0.1,1,1)稍微向下移動此bouding框以防止圖例被放置在其他藝術家之上。

OBS:在您使用fig.set_size_inches()並在您使用fig.tight_layout()

+1

或者simpy'loc ='upper center',bbox_to_anchor =(0.5,0),bbox_transform = plt.gcf()。transFigure',它不會重疊。 – 2016-08-07 11:45:17

+1

我仍然不確定爲什麼,但Evert的解決方案對我無效 - 這個傳說不斷被切斷。這個解決方案(和davor的評論一起)非常乾淨地工作 - 傳說被放置如預期並且完全可見。謝謝! – 2016-12-11 13:41:20

7

還有一個很好的功能get_legend_handles_labels()您可以在最後一個軸打電話(如果你在它們之間迭代),將收集你所需要的一切使用此解決方案label=自變量:

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

這應該是最好的答案。 – naught101 2017-12-04 07:28:47

0

這個答案是對@埃弗特在傳說中的補充。

由於圖例和子圖的標題重疊,我第一次嘗試@ Evert的解決方案失敗。

實際上,重疊是由fig.tight_layout()引起的,它會在不考慮圖形圖例的情況下更改子圖的佈局。但是,fig.tight_layout()是必要的。

爲了避免重疊,我們可以告訴fig.tight_layout()給圖形的圖例留出空間fig.tight_layout(rect=(0,0,1,0.9))

Description of tight_layout() parameters

相關問題