2016-07-28 6 views
10

matplotlibで複雑な凡例を作りたいと思います。 enter image description herematplotlibの表の凡例

しかし、私はここのような複雑な伝説をプロットしたいと思います:

enter image description here

私もやってみました私は、次のコード

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() 

それはそのようなプロットを作成をしました凡例tableと機能しますが、私はセルの適切な位置にテーブルにパッチオブジェクトを配置することはできません。

+0

私は肯定的ではないが、私は、[この]に受け入れ答えでまさにそれをやっ例があると信じています(http ://stackoverflow.com/questions/21570007/custom-legend-in-matplotlib)question。それとも少なくとも正しい方向に向けるかもしれませんか? – Ajean

+0

いいえ、その例ではすべてのマーカーに独自のラベルがあります。 – Serenity

+0

そうですが、そこに空文字列を置くことができます。私は実際に私がここで見た別の例を探していた(誰かが美しさの伝説を書いた)が、私はそれを追跡できなかった。私は空の文字列を使ったと思うので、ちょっと考えました。申し訳ありませんが、私はそれを見つけることができません... – Ajean

答えて

3

が自分の好みに十分に近いこのソリューションですか?リカルドの答えには少し触発されていましたが、各列に1つの凡例オブジェクトしか使用せず、titleキーワードを使用して個々の列のタイトルを設定しました。各列の中央にマーカーを置くために、私は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

はい、あまりにも注意してください...私の編集された答えをご覧ください。いくつかのラベルを使用する代わりに、すべてを1つのラベルに置き換えました。今行われなければならない唯一の調整は、 '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

Iは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

関連する問題