python - 位置 - matplotlib テキストボックス




伝説をプロットの外に置く方法 (11)

凡例を配置する( bbox_to_anchor

凡例は、 plt.legendへのloc引数を使用して、軸の境界ボックスの内側に配置されます。
例えば、右上には、境界ボックスの右上隅に凡例が配置されます。デフォルトでは、軸座標(または境界ボックス記法(x0,y0, width, height)=(0,0,1,1) )。

凡例を軸の外枠の外側に配置するには、凡例の左下隅の軸座標のタプル(x0,y0)を指定することができます。

plt.legend(loc=(1.04,0))

しかし、より汎用的なアプローチは、 bbox_to_anchor引数を使用して、凡例を配置するバウンディングボックスを手動で指定することです。 bboxの(x0,y0)部分だけを供給するように自分自身を制限することができます。 これにより、凡例がloc引数によって与えられた方向に展開されるゼロスパンボックスが作成されます。 例えば

plt.legend(bbox_to_anchor=(1.04,1), loc="upper left")

凡例の左上隅が軸座標の位置(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")

bbox_to_anchorように4タプルの引数をbbox_to_anchorに解釈する方法の詳細は、 この質問にあります。 mode="expand"は、4タプルによって与えられたバウンディングボックス内で、凡例を水平方向に展開します。 垂直方向に拡張された凡例については、 この質問を参照してください。

場合によっては、座標軸の代わりに図形座標で境界ボックスを指定すると便利なことがあります。 これは、図の左下隅に凡例を置くためにbbox_transform引数が使用される上の例のbbox_transform示されています。

後処理

伝説を軸の外側に置くと、それが完全にまたは部分的にフィギュアキャンバスの外にあるという望ましくない状況になることがよくあります。

この問題の解決方法は次のとおりです。

  • サブプロットのパラメータを調整する
    plt.subplots_adjustを使用すると、軸が図の内部のスペースを少なくして(したがって、凡例に多くのスペースを残すように)サブプロットのパラメータを調整できます。 例えば

    plt.subplots_adjust(right=0.7)
    

    凡例を置くことができる図の右側に30%のスペースを残す。

  • タイトなレイアウト
    plt.tight_layoutを使用する図の要素がFigureの端にplt.tight_layoutように、サブプロットのパラメータを自動的に調整できます。 残念なことに、このオートマトンでは伝説は考慮されませんが、ラベルを含むサブプロット領域全体が収まる四角形のボックスを提供できます。

    plt.tight_layout(rect=[0,0,0.75,1])
    
  • bbox_inches = "tight"図を保存する
    引数bbox_inches = "tight"plt.savefigに使用すると、キャンバス上のすべてのアーティスト(凡例を含む)が保存された領域に収まるようにFigureを保存できます。 必要に応じて、Figureのサイズが自動的に調整されます。

    plt.savefig("output.png", bbox_inches="tight")
    
  • サブプロットパラメータを自動的に調整する
    凡例が図形のサイズを変更することなくキャンバス内に収まるように、サブプロットの位置を自動的に調整する方法は、この回答に記載されています。 正確なサイズとパディングなしの図形の作成(および軸の外の凡例)

上記のケース間の比較:

代替案

図の伝説
図形の凡例は、軸、 matplotlib.figure.Figure.legend代わりに使用できます。 これは、特別な引数が必要でないmatplotlib version> = 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 )に凡例をbbox_to_anchorすることもできます。 凡例のサブプロットはプロットより小さくする必要があるので、 gridspec_kw={"width_ratios":[4,1]}を軸の作成に使用することができます。 軸lax.axis("off")は隠すことができますが、凡例を入れます。凡例のハンドルとラベルは、 h,l = ax.get_legend_handles_labels()を介して実際のプロットから取得する必要があります。 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()

上のプロットと視覚的にかなり似ているプロットが生成されます。

また、第1の軸を使用して凡例を配置することもできますが、凡例軸のbbox_transformを使用して、

ax.legend(bbox_to_anchor=(0,0,1,1), bbox_transform=lax.transAxes)
lax.axis("off")

このアプローチでは、凡例ハンドルを外部から取得する必要はありませんが、 bbox_to_anchor引数を指定する必要があります。

さらなる読書とメモ:

  • 伝説でやりたいことのいくつかの例を挙げてmatplotlibの伝説のガイドを考えてみましょう。
  • 円グラフの凡例を配置するためのいくつかのコード例は、この質問の答えに直接見つけることができます: Python - 凡例が円グラフと重なっている
  • loc引数は文字列の代わりに数字をとることができますが、これは呼び出しを短くしますが、互いに直感的にはマッピングされません。 参照用のマッピングは次のとおりです。

私は20のプロット(サブプロットではない)を1つの図形で作っています。 私は伝説が箱の外にあることを望む。 同時に、図のサイズが小さくなるので、軸を変更したくないです。 以下の質問にお役立てください。

  1. 私はプロットエリアの外に伝説のボックスを保持したい。 (私は、プロット領域の右側に外側に伝説が欲しい)。
  2. とにかく、凡例ボックス内のテキストのフォントサイズを小さくして、凡例ボックスのサイズが小さくなるようにしますか?

plot()コールの後でlegend()コールを次のように呼び出すだけです:

# matplotlib
plt.plot(...)
plt.legend(loc='center left', bbox_to_anchor=(1, 0.5))

# Pandas
df.myCol.plot().legend(loc='center left', bbox_to_anchor=(1, 0.5))

結果は次のようになります。


あなたが望むことをするにはいくつかの方法があります。 @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()

あるいは、現在のプロットの幅を縮小し、凡例を図の軸の外側に完全に配置することもできます。

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()見てみることもできます。 とにかく少し助けてくれることを願っています!


あなたの問題を既に整理しているかどうかは分かりません...おそらくはい、しかし...私は単純に場所の文字列を 'matlab'のように使いました。 私はmatplotlibからピラブを輸入しました。 次のコードを参照してください。

from matplotlib as plt
from matplotlib.font_manager import FontProperties
...
...
t = A[:,0]
sensors = A[:,index_lst]

for i in range(sensors.shape[1]):
    plt.plot(t,sensors[:,i])

plt.xlabel('s')
plt.ylabel('°C')
lgd = plt.legend(b,loc='center left', bbox_to_anchor=(1, 0.5),fancybox = True, shadow = True)

プロットを見るにはクリックしてください


ここでのすばらしい答えに加えて、新しいバージョンのmatplotlibpylab、プロットを妨げずに凡例をどこに置くべきか自動的に決定することができます

pylab.legend(loc='best')

これは自動的にプロットの外に凡例を置きます!


ここにmatplotlibチュートリアルの例を示します 。 これはより簡単な例の1つですが、私は凡例に透明度を追加し、これを対話型シェルに貼り付けて結果を得ることができるようにplt.show()を追加しました:

import matplotlib.pyplot as plt
p1, = plt.plot([1, 2, 3])
p2, = plt.plot([3, 2, 1])
p3, = plt.plot([2, 3, 1])
plt.legend([p2, p1, p3], ["line 1", "line 2", "line 3"]).get_frame().set_alpha(0.5)
plt.show()

フォントプロパティを作成する

from matplotlib.font_manager import FontProperties

fontP = FontProperties()
fontP.set_size('small')
legend([plot1], "title", prop=fontP)

凡例をプロット領域外に配置するには、legend()のlocおよびbbox_to_anchorキーワードを使用します。 たとえば、次のコードは、凡例をプロット領域の右側に配置します。

legend(loc="upper left", bbox_to_anchor=(1,1))

詳細は、 凡例のガイドを参照してください。


前述したように、凡例をプロットに配置することも、凡例をエッジにわずかに配置することもできます。 ここでは、 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}を選択します


正確にはあなたが求めているものではありませんが、私はそれが同じ問題の代替手段であることを発見しました。 伝説を半透明にしましょう。

これを行うには:

fig = pylab.figure()
ax = fig.add_subplot(111)
ax.plot(x,y,label=label,color=color)
# Make the legend transparent:
ax.legend(loc=2,fontsize=10,fancybox=True).get_frame().set_alpha(0.5)
# Make a transparent text box
ax.text(0.02,0.02,yourstring, verticalalignment='bottom',
                     horizontalalignment='left',
                     fontsize=10,
                     bbox={'facecolor':'white', 'alpha':0.6, 'pad':10},
                     transform=self.ax.transAxes)

私が偉大な伝説を持っていたとき私のために働いた解決策は、余分な空の画像レイアウトを使うことでした。 次の例では、4行作成し、最下部に凡例(bbox_to_anchor)のオフセットを付けて上書きします。

f = plt.figure()
ax = f.add_subplot(414)
lgd = ax.legend(loc='upper left', bbox_to_anchor=(0, 4), mode="expand", borderaxespad=0.3)
ax.autoscale_view()
plt.savefig(fig_name, format='svg', dpi=1200, bbox_extra_artists=(lgd,), bbox_inches='tight')




legend