一連の 20 個のプロット (サブプロットではない) を 1 つの図に作成します。凡例を枠の外に出してほしい。同時に、図のサイズが縮小されるため、軸を変更したくありません。次のクエリについて教えてください。
- プロット エリアの外に凡例ボックスを保持したい。(凡例をプロット領域の右側の外側にしたい)。
- とにかく、凡例ボックスのサイズが小さくなるように、凡例ボックス内のテキストのフォントサイズを小さくすることはありますか?
一連の 20 個のプロット (サブプロットではない) を 1 つの図に作成します。凡例を枠の外に出してほしい。同時に、図のサイズが縮小されるため、軸を変更したくありません。次のクエリについて教えてください。
あなたがやりたいことをする方法はたくさんあります。@inalisと@Naviがすでに言ったことに追加するには、bbox_to_anchor
キーワード引数を使用して、凡例を軸の外側に部分的に配置したり、フォントサイズを小さくしたりできます。
フォントサイズを小さくすることを検討する前に(これにより、読みにくくなる可能性があります)、凡例をさまざまな場所に配置してみてください。
それでは、一般的な例から始めましょう。
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(10)
fig = plt.figure()
ax = plt.subplot(111)
for i in xrange(5):
ax.plot(x, i * x, label='$y = %ix$' % i)
ax.legend()
plt.show()
同じことを行うが、bbox_to_anchor
キーワード引数を使用すると、凡例を軸の境界の少し外側にシフトできます。
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(10)
fig = plt.figure()
ax = plt.subplot(111)
for i in xrange(5):
ax.plot(x, i * x, label='$y = %ix$' % i)
ax.legend(bbox_to_anchor=(1.1, 1.05))
plt.show()
同様に、凡例をより水平にするか、図の上部に配置します(丸みを帯びた角と単純なドロップシャドウもオンにします)。
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(10)
fig = plt.figure()
ax = plt.subplot(111)
for i in xrange(5):
line, = ax.plot(x, i * x, label='$y = %ix$'%i)
ax.legend(loc='upper center', bbox_to_anchor=(0.5, 1.05),
ncol=3, fancybox=True, shadow=True)
plt.show()
または、現在のプロットの幅を縮小し、凡例を図の軸の完全に外側に配置します(注:を使用する場合はtight_layout()
、省略してax.set_position()
ください:
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(10)
fig = plt.figure()
ax = plt.subplot(111)
for i in xrange(5):
ax.plot(x, i * x, label='$y = %ix$'%i)
# Shrink current axis by 20%
box = ax.get_position()
ax.set_position([box.x0, box.y0, box.width * 0.8, box.height])
# Put a legend to the right of the current axis
ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))
plt.show()
同様の方法で、プロットを垂直方向に縮小し、下部に水平方向の凡例を配置します。
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(10)
fig = plt.figure()
ax = plt.subplot(111)
for i in xrange(5):
line, = ax.plot(x, i * x, label='$y = %ix$'%i)
# Shrink current axis's height by 10% on the bottom
box = ax.get_position()
ax.set_position([box.x0, box.y0 + box.height * 0.1,
box.width, box.height * 0.9])
# Put a legend below current axis
ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.05),
fancybox=True, shadow=True, ncol=5)
plt.show()
matplotlibの凡例ガイドをご覧ください。もご覧くださいplt.figlegend()
。
bbox_to_anchor
)loc
引数 toを使用して、軸の境界ボックス内に凡例を配置しplt.legend
ます。
たとえばloc="upper right"
、凡例を境界ボックスの右上隅に配置します。デフォルトでは、軸座標 (または境界ボックスの表記法) で から(0,0)
までの範囲になります。(1,1)
(x0,y0, width, height)=(0,0,1,1)
凡例を軸境界ボックスの外側に配置するには(x0,y0)
、凡例の左下隅の軸座標のタプルを指定できます。
plt.legend(loc=(1.04,0))
より用途の広いアプローチは、bbox_to_anchor
引数を使用して、凡例を配置する境界ボックスを手動で指定することです。(x0, y0)
bboxの一部のみを提供するように制限することができます。これによりゼロ スパン ボックスが作成され、そこから凡例がloc
引数で指定された方向に拡張されます。例えば
plt.legend(bbox_to_anchor=(1.04,1), loc="左上")
凡例の左上隅が(1.04,1)
軸座標の位置になるように、凡例を軸の外側に配置します。
さらなる例を以下に示します。さらに、mode
とのような異なる引数間の相互作用ncols
が示されています。
l1 = plt.legend(bbox_to_anchor=(1.04,1), borderaxespad=0)
l2 = plt.legend(bbox_to_anchor=(1.04,0), loc="lower left", borderaxespad=0)
l3 = plt.legend(bbox_to_anchor=(1.04,0.5), loc="center left", borderaxespad=0)
l4 = plt.legend(bbox_to_anchor=(0,1.02,1,0.2), loc="lower left",
mode="expand", borderaxespad=0, ncol=3)
l5 = plt.legend(bbox_to_anchor=(1,0), loc="lower right",
bbox_transform=fig.transFigure, ncol=3)
l6 = plt.legend(bbox_to_anchor=(0.4,0.8), loc="upper right")
のように への 4 タプル引数を解釈する方法の詳細についてはbbox_to_anchor
、l4
この質問を参照してください。はmode="expand"
、4 タプルで指定されたバウンディング ボックス内で凡例を水平方向に拡張します。縦に展開された凡例については、この質問を参照してください。
軸座標ではなく Figure 座標で境界ボックスを指定すると便利な場合があります。これはl5
上の例に示されています。bbox_transform
引数は、図の左下隅に凡例を配置するために使用されます。
凡例を軸の外側に配置すると、凡例が完全にまたは部分的に Figure キャンバスの外側にあるという望ましくない状況につながることがよくあります。
この問題の解決策は次のとおりです。
サブプロット パラメータ
を調整する を使用して、軸が Figure 内のスペースを少なくする (したがって、凡例により多くのスペースを残す) ように、サブプロット パラメータを調整できますplt.subplots_adjust
。例えば
plt.subplots_adjust(right=0.7)
図の右側に凡例を配置できる 30% のスペースを残します。
タイト レイアウト
使用法plt.tight_layout
サブプロット パラメーターを自動的に調整して、Figure 内の要素が Figure の端に密着するようにします。残念ながら、この自動化では凡例は考慮されていませんが、サブプロット領域全体 (ラベルを含む) が収まる長方形のボックスを提供できます。
plt.tight_layout(rect=[0,0,0.75,1])
bbox_inches = "tight"
引数bbox_inches = "tight"
toを使用して図plt.savefig
を保存すると、キャンバス上のすべてのアーティスト (凡例を含む) が保存領域に収まるように図を保存できます。必要に応じて、Figure のサイズが自動的に調整されます。
plt.savefig("output.png", bbox_inches="tight")
サブプロット パラメータを自動的に調整する 図のサイズを変更せず
に凡例がキャンバスの内側に収まるようにサブプロットの位置を自動的に調整する方法は、この回答にあります。
上記のケースの比較:
フィギュア伝説
軸の代わりに図に凡例を使用することができますmatplotlib.figure.Figure.legend
。これは、特別な引数が不要な matplotlib バージョン >=2.1 で特に便利になりました。
fig.legend(loc=7)
図のさまざまな軸ですべてのアーティストの凡例を作成します。凡例は、loc
引数を使用して配置されます。これは、軸の内側に配置する方法と同様ですが、図全体を参照するため、自動的に軸の外側になります。残っているのは、凡例と軸の間に重複がないようにサブプロットを調整することです。ここで、上記の「サブプロットパラメーターを調整する」というポイント が役立ちます。例:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0,2*np.pi)
colors=["#7aa0c4","#ca82e1" ,"#8bcd50","#e18882"]
fig, axes = plt.subplots(ncols=2)
for i in range(4):
axes[i//2].plot(x,np.sin(x+i), color=colors[i],label="y=sin(x+{})".format(i))
fig.legend(loc=7)
fig.tight_layout()
fig.subplots_adjust(right=0.75)
plt.show()
専用サブプロット軸内の凡例
を使用bbox_to_anchor
する代わりに、凡例を専用のサブプロット軸 ( lax
) に配置することもできます。凡例のサブプロットはプロットよりも小さくする必要があるためgridspec_kw={"width_ratios":[4,1]}
、軸の作成時に使用できます。軸を非表示にできますがlax.axis("off")
、凡例を入れます。凡例のハンドルとラベルは、 を介して実際のプロットから取得する必要があり、サブプロットh,l = ax.get_legend_handles_labels()
の凡例に提供できます。完全な例を以下に示します。lax
lax.legend(h,l)
import matplotlib.pyplot as plt
plt.rcParams["figure.figsize"] = 6,2
fig, (ax,lax) = plt.subplots(ncols=2, gridspec_kw={"width_ratios":[4,1]})
ax.plot(x,y, label="y=sin(x)")
....
h,l = ax.get_legend_handles_labels()
lax.legend(h,l, borderaxespad=0)
lax.axis("off")
plt.tight_layout()
plt.show()
これにより、上のプロットと視覚的に非常によく似たプロットが生成されます。
最初の軸を使用して凡例を配置することもできますがbbox_transform
、凡例の軸の を使用します。
ax.legend(bbox_to_anchor=(0,0,1,1), bbox_transform=lax.transAxes)
lax.axis("off")
このアプローチでは、凡例ハンドルを外部から取得する必要はありませんが、bbox_to_anchor
引数を指定する必要があります。
loc
代わりに数値を取ることができるため、呼び出しが短くなりますが、相互に直感的にマッピングされるわけではありません。参照用のマッピングは次のとおりです。set_size
ofを指定することで、凡例の文字を小さくすることができますFontProperties
。matplotlib.legend
matplotlib.pyplot.legend
matplotlib.font_manager
set_size(self, size)
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
fontP = FontProperties()
fontP.set_size('xx-small')
p1, = plt.plot([1, 2, 3], label='Line 1')
p2, = plt.plot([3, 2, 1], label='Line 2')
plt.legend(handles=[p1, p2], title='title', bbox_to_anchor=(1.05, 1), loc='upper left', prop=fontP)
fontsize='xx-small'
インポートせずに動作しFontProperties
ます。plt.legend(handles=[p1, p2], title='title', bbox_to_anchor=(1.05, 1), loc='upper left', fontsize='xx-small')
凡例をプロット エリアの外に配置するには、 と のキーワードを使用loc
しbbox_to_anchor
ますlegend()
。たとえば、次のコードは凡例をプロット エリアの右側に配置します。
legend(loc="upper left", bbox_to_anchor=(1,1))
詳細については、凡例ガイドを参照してください
ここでのすべての優れた回答に加えて、新しいバージョンのmatplotlib
とは、可能であれば、プロットに干渉することなく凡例を配置する場所を自動的に決定pylab
できます。
pylab.legend(loc='best')
これにより、可能であれば凡例が自動的にデータから離れた場所に配置されます。
ただし、データをオーバーラップせずに凡例を配置する場所がない場合は、他の回答のいずれかを試してください。を使用loc="best"
すると、凡例がプロットの外に出ることはありません。
簡単な回答:凡例でドラッグ可能なものを呼び出して、好きな場所にインタラクティブに移動します。
ax.legend().draggable()
長い回答:プログラムではなくインタラクティブ/手動で凡例を配置したい場合は、凡例のドラッグ可能なモードを切り替えて、好きな場所にドラッグできるようにすることができます。以下の例を確認してください。
import matplotlib.pylab as plt
import numpy as np
#define the figure and get an axes instance
fig = plt.figure()
ax = fig.add_subplot(111)
#plot the data
x = np.arange(-5, 6)
ax.plot(x, x*x, label='y = x^2')
ax.plot(x, x*x*x, label='y = x^3')
ax.legend().draggable()
plt.show()
Matplotlib の新しいバージョンでは、凡例をプロットの外に配置することがはるかに簡単になったため、この質問を更新する価値があります。この例は Matplotlib version で作成し3.1.1
ました。
ユーザーはloc
、境界ボックス内の任意の場所に凡例を配置するために、パラメーターに座標の 2 タプルを渡すことができます。plt.tight_layout()
唯一の落とし穴は、matplotlib を実行してプロットの次元を再計算し、凡例が表示されるようにする必要があることです。
import matplotlib.pyplot as plt
plt.plot([0, 1], [0, 1], label="Label 1")
plt.plot([0, 1], [0, 2], label='Label 2')
plt.legend(loc=(1.05, 0.5))
plt.tight_layout()
これにより、次のプロットが得られます。
参考文献:
前述のように、凡例をプロットに配置することも、端まで少しずらして配置することもできます。これは、 IPython Notebookで作成されたPlotly Python APIを使用した例です。私はチームにいます。
まず、必要なパッケージをインストールします。
import plotly
import math
import random
import numpy as np
次に、Plotly をインストールします。
un='IPython.Demo'
k='1fw3zw2o13'
py = plotly.plotly(username=un, key=k)
def sin(x,n):
sine = 0
for i in range(n):
sign = (-1)**i
sine = sine + ((x**(2.0*i+1))/math.factorial(2*i+1))*sign
return sine
x = np.arange(-12,12,0.1)
anno = {
'text': '$\\sum_{k=0}^{\\infty} \\frac {(-1)^k x^{1+2k}}{(1 + 2k)!}$',
'x': 0.3, 'y': 0.6,'xref': "paper", 'yref': "paper",'showarrow': False,
'font':{'size':24}
}
l = {
'annotations': [anno],
'title': 'Taylor series of sine',
'xaxis':{'ticks':'','linecolor':'white','showgrid':False,'zeroline':False},
'yaxis':{'ticks':'','linecolor':'white','showgrid':False,'zeroline':False},
'legend':{'font':{'size':16},'bordercolor':'white','bgcolor':'#fcfcfc'}
}
py.iplot([{'x':x, 'y':sin(x,1), 'line':{'color':'#e377c2'}, 'name':'$x\\\\$'},\
{'x':x, 'y':sin(x,2), 'line':{'color':'#7f7f7f'},'name':'$ x-\\frac{x^3}{6}$'},\
{'x':x, 'y':sin(x,3), 'line':{'color':'#bcbd22'},'name':'$ x-\\frac{x^3}{6}+\\frac{x^5}{120}$'},\
{'x':x, 'y':sin(x,4), 'line':{'color':'#17becf'},'name':'$ x-\\frac{x^5}{120}$'}], layout=l)
これによりグラフが作成され、凡例をプロット自体に保持することができます。設定されていない場合の凡例のデフォルトは、ここに示すようにプロットに配置することです。
別の配置として、グラフの端と凡例の境界線をぴったりと揃えて、境界線を削除してぴったり合わせることができます。
コードまたは GUI を使用して、凡例とグラフの移動とスタイル変更を行うことができます。凡例をシフトするには、x と y の値に <= 1 を割り当てることで凡例をグラフ内に配置する次のオプションがあります。例:
{"x" : 0,"y" : 0}
- 左下の{"x" : 1, "y" : 0}
- 右下{"x" : 1, "y" : 1}
- 右上{"x" : 0, "y" : 1}
- 左上{"x" :.5, "y" : 0}
-- 下中央{"x": .5, "y" : 1}
-- トップセンターこの場合、ドキュメントlegendstyle = {"x" : 1, "y" : 1}
にも記載されている右上の を選択します。
これらの線に沿った何かが私にとってうまくいきました。Joe から取った少しのコードから始めて、このメソッドはウィンドウの幅を変更して、図の右側に凡例が自動的に収まるようにします。
import matplotlib.pyplot as plt
import numpy as np
plt.ion()
x = np.arange(10)
fig = plt.figure()
ax = plt.subplot(111)
for i in xrange(5):
ax.plot(x, i * x, label='$y = %ix$'%i)
# Put a legend to the right of the current axis
leg = ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))
plt.draw()
# Get the ax dimensions.
box = ax.get_position()
xlocs = (box.x0,box.x1)
ylocs = (box.y0,box.y1)
# Get the figure size in inches and the dpi.
w, h = fig.get_size_inches()
dpi = fig.get_dpi()
# Get the legend size, calculate new window width and change the figure size.
legWidth = leg.get_window_extent().width
winWidthNew = w*dpi+legWidth
fig.set_size_inches(winWidthNew/dpi,h)
# Adjust the window size to fit the figure.
mgr = plt.get_current_fig_manager()
mgr.window.wm_geometry("%ix%i"%(winWidthNew,mgr.window.winfo_height()))
# Rescale the ax to keep its original size.
factor = w*dpi/winWidthNew
x0 = xlocs[0]*factor
x1 = xlocs[1]*factor
width = box.width*factor
ax.set_position([x0,ylocs[0],x1-x0,ylocs[1]-ylocs[0]])
plt.draw()
試すこともできますfiglegend
。Axesオブジェクトから独立して凡例を作成することができます。ただし、オブジェクトのフォーマットが正しく渡されるように、いくつかの「ダミー」パスを作成する必要がある場合があります。