2016-07-28 55 views
10

我想在matplotlib中創建一個複雜的圖例。我做了下面的代碼matplotlib中的表格圖例

import matplotlib.pylab as plt 
import numpy as np 

N = 25 
y = np.random.randn(N) 
x = np.arange(N) 

y2 = np.random.randn(25) 

# serie A 
p1a, = plt.plot(x, y,  "ro", ms=10, mfc="r", mew=2, mec="r") 
p1b, = plt.plot(x[:5], y[:5] , "w+", ms=10, mec="w", mew=2) 
p1c, = plt.plot(x[5:10], y[5:10], "w*", ms=10, mec="w", mew=2) 

# serie B 
p2a, = plt.plot(x, y2,  "bo", ms=10, mfc="b", mew=2, mec="b") 
p2b, = plt.plot(x[15:20], y2[15:20] , "w+", ms=10, mec="w", mew=2) 
p2c, = plt.plot(x[10:15], y2[10:15], "w*", ms=10, mec="w", mew=2) 


plt.legend([p1a, p2a, (p1a, p1b), (p2a,p2b), (p1a, p1c), (p2a,p2c)], 
["No prop", "No prop", "Prop +", "Prop +", "Prop *", "Prop *"], ncol=3, numpoints=1) 

plt.show() 

它生產的情節那樣: enter image description here

但我想繪製複雜的傳奇喜歡這裏:

enter image description here

我也試着做table函數的傳說,但我不能將一個修補程序對象放到表格中的適當位置的單元格。

+0

我還不能肯定,但我相信這正是做在接受的答案爲[這裏]爲例(HTTP ://stackoverflow.com/questions/21570007/custom-legend-in-matplotlib)問題。或者它至少可以讓你指向正確的方向? – Ajean

+0

不,在這個例子中,每個標記都有自己的標籤。 – Serenity

+0

沒錯,但你可以在那裏放空弦。我實際上是在尋找一個我以前在這裏看到過的不同例子(有人寫了一個美麗的傳說),但我無法追蹤它。只是一個想法,因爲我認爲一個使用空字符串。對不起,我找不到它... – Ajean

回答

3

這是解決方案足夠接近自己的喜好?它的靈感來自於裏卡多的回答,但我只用了每個列的一個圖例對象,然後利用關鍵字設置每個列的標題。要把標記放在每列的中心,我用handletextpad以負值將它向後推。沒有傳說給個別的線路。我還必須在標題字符串中插入一些空格,以便在屏幕上繪製時看起來同樣大。

現在我還注意到,當保存圖形時,需要對圖例框的確切位置進行額外的調整,但是因爲我想你可能想要在代碼中調整更多的東西,無論如何我都會爲你保留它。您可能還需要玩handletextpad,以使它們「完美」對齊。

import matplotlib.pylab as plt 
import numpy as np 
plt.close('all') 

N = 25 
y = np.random.randn(N) 
x = np.arange(N) 

y2 = np.random.randn(25) 

# serie A 
p1a, = plt.plot(x, y,  "ro", ms=10, mfc="r", mew=2, mec="r") 
p1b, = plt.plot(x[:5], y[:5] , "w+", ms=10, mec="w", mew=2) 
p1c, = plt.plot(x[5:10], y[5:10], "w*", ms=10, mec="w", mew=2) 

# serie B 
p2a, = plt.plot(x, y2,  "bo", ms=10, mfc="b", mew=2, mec="b") 
p2b, = plt.plot(x[15:20], y2[15:20] , "w+", ms=10, mec="w", mew=2) 
p2c, = plt.plot(x[10:15], y2[10:15], "w*", ms=10, mec="w", mew=2) 

line_columns = [ 
       p1a, p2a, 
       (p1a, p1b), (p2a, p2b), 
       (p1a, p1c), (p2a, p2c) 
       ] 


leg1 = plt.legend(line_columns[0:2], ['', ''], ncol=1, numpoints=1, 
        title='No prop', handletextpad=-0.4, 
        bbox_to_anchor=[0.738, 1.]) 
leg2 = plt.legend(line_columns[2:4], ['', ''], ncol=1, numpoints=1, 
        title=' Prop + ', handletextpad=-0.4, 
        bbox_to_anchor=[0.87, 1.]) 
leg3 = plt.legend(line_columns[4:6], ['', ''], ncol=1, numpoints=1, 
        title=' Prop * ', handletextpad=-0.4, 
        bbox_to_anchor=[0.99, 1.]) 

plt.gca().add_artist(leg1) 
plt.gca().add_artist(leg2) 
plt.gca().add_artist(leg3) 

plt.gcf().show() 

enter image description here

編輯

也許這將更好地工作。你仍然需要調整一些東西,但是bbox的對齊問題已經消失了。

leg = plt.legend(line_columns, ['']*len(line_columns), 
      title='No Prop Prop + Prop *', 
      ncol=3, numpoints=1, handletextpad=-0.5) 

enter image description here

+0

很難把這個傳說正確的,因爲錨點不計算自動設置 – Serenity

+0

是的,也請注意......請看我編輯的答案。我用一個標籤替換了所有標籤,而不是使用多個標籤。現在唯一需要做的調整就是使用'title'和'handletextpad'值的內部空格。這是否更好? – pathoren

+0

很好,很漂亮。謝謝。 – Serenity

2

似乎沒有標準的方法,而不是這裏可用的一些技巧。

值得一提的是,你應該檢查最適合你的大小bbox因子。

我能找到到目前爲止最好的,也許是一個可以帶你到一個更好的解決方案:

N = 25 
y = np.random.randn(N) 
x = np.arange(N) 

y2 = np.random.randn(25) 

# Get current size 
fig_size = list(plt.rcParams["figure.figsize"]) 

# Set figure width to 12 and height to 9 
fig_size[0] = 12 
fig_size[1] = 12 
plt.rcParams["figure.figsize"] = fig_size 

# serie A 
p1a, = plt.plot(x, y,  "ro", ms=10, mfc="r", mew=2, mec="r") 
p1b, = plt.plot(x[:5], y[:5] , "w+", ms=10, mec="w", mew=2) 
p1c, = plt.plot(x[5:10], y[5:10], "w*", ms=10, mec="w", mew=2) 

# serie B 
p2a, = plt.plot(x, y2,  "bo", ms=10, mfc="b", mew=2, mec="b") 
p2b, = plt.plot(x[15:20], y2[15:20] , "w+", ms=10, mec="w", mew=2) 
p2c, = plt.plot(x[10:15], y2[10:15], "w*", ms=10, mec="w", mew=2) 

v_factor = 1. 
h_factor = 1. 

leg1 = plt.legend([(p1a, p1a)], ["No prop"], bbox_to_anchor=[0.78*h_factor, 1.*v_factor]) 
leg2 = plt.legend([(p2a, p2a)], ["No prop"], bbox_to_anchor=[0.78*h_factor, .966*v_factor]) 

leg3 = plt.legend([(p2a,p2b)], ["Prop +"], bbox_to_anchor=[0.9*h_factor, 1*v_factor]) 
leg4 = plt.legend([(p1a, p1b)], ["Prop +"], bbox_to_anchor=[0.9*h_factor, .966*v_factor]) 

leg5 = plt.legend([(p1a, p1c)], ["Prop *"], bbox_to_anchor=[1.*h_factor, 1.*v_factor]) 
leg6 = plt.legend([(p2a,p2c)], ["Prop *"], bbox_to_anchor=[1.*h_factor, .966*v_factor]) 

plt.gca().add_artist(leg1) 
plt.gca().add_artist(leg2) 
plt.gca().add_artist(leg3) 
plt.gca().add_artist(leg4) 
plt.gca().add_artist(leg5) 
plt.gca().add_artist(leg6) 
plt.show() 

enter image description here

1

我根據BBOX傳說的座標提高@pathoren到位置傳說的答案在一個週期自動。此代碼允許顯示了複雜的傳奇的一切所需的邊界線:

import matplotlib.pylab as plt 
import numpy as np 
plt.close('all') 

# test data 
N = 25 
y = np.random.randn(N) 
x = np.arange(N) 
y2 = np.random.randn(25) 

# serie A 
p1a, = plt.plot(x, y, "ro", ms=10, mfc="r", mew=2, mec="r") 
p1b, = plt.plot(x[:5], y[:5], "w+", ms=10, mec="w", mew=2) 
p1c, = plt.plot(x[5:10], y[5:10], "w*", ms=10, mec="w", mew=2) 
# serie B 
p2a, = plt.plot(x, y2, "bo", ms=10, mfc="b", mew=2, mec="b") 
p2b, = plt.plot(x[15:20], y2[15:20], "w+", ms=10, mec="w", mew=2) 
p2c, = plt.plot(x[10:15], y2[10:15], "w*", ms=10, mec="w", mew=2) 

# legend handlers 
columns = [p1a, p2a, 
(p1a, p1b), (p2a, p2b), 
(p1a, p1c), (p2a, p2c)] 

ax = plt.gca() 
fig = plt.gcf() 
legs = [] 
# set the first legend in desired position 
leg = plt.legend(columns[0:2], ['', ''], ncol=1, numpoints=1, 
borderaxespad=0., title='No prop.', framealpha=.75, 
facecolor='w', edgecolor='k', loc=2, fancybox=None) 
ax.add_artist(leg) 
fig.canvas.draw() 
plt.pause(1.e-3) 

# get bbox postion of 1st legend to calculate 
# postion of 2nd and 3rd legends according to loc 
for i,si in enumerate(['+','*']): 
    bbox = leg.get_window_extent().inverse_transformed(ax.transAxes) 
    # next legends 
    leg = plt.legend(columns[(i+1)*2:(i+1)*2+2], ['', ''], ncol=1, numpoints=1, 
    title='Prop. '+si, framealpha=.75, borderaxespad=.0, 
    bbox_to_anchor=(bbox.x1-bbox.height*.08, bbox.y0, bbox.width, bbox.height), 
    facecolor='w', edgecolor='k') 
    ax.add_artist(leg) 
    fig.canvas.draw() 
    plt.pause(1.e-3) 

plt.show() 

enter image description here