web-dev-qa-db-ja.com

プロット外のMatplotlib自動凡例

Pythonのmatplotlibプロットでキーワードbbox_to_anchor()を使用しようとしています。

これは私が作成した非常に基本的なプロットです。

_import matplotlib.pyplot as plt
x = [1,2,3]
plt.subplot(211)
plt.plot(x, label="test1")
plt.plot([3,2,1], label="test2")
plt.legend(bbox_to_anchor=(0, -0.15, 1, 0), loc=2, ncol=2, mode="expand", borderaxespad=0)
plt.show()
_

次の例に基づいています: http://matplotlib.org/users/legend_guide.html#plotting-guide-legend

bbox_to_anchor()を使用して、プロットの外側に凡例を自動的に配置しようとしています。この例では、bbox_to_anchor()には4つの引数がリストされています。

この特定の例(上記)では、凡例をプロットの下に配置しているため、プロットを変更するたびに(フォントサイズ、軸タイトルを削除するなど)数値-0.15を手動で入力する必要があります。 次のシナリオでこれらの4つの数値を自動的に計算することは可能ですか?

  1. プロットの下の凡例
  2. プロット上の凡例
  3. プロットの右側の凡例

そうでない場合、Pythonでこれらの数値について適切に推測することは可能ですか?

また、上記のサンプルコードでは、bbox_to_anchor()の最後の2つの数値を1と0に設定しています。これは、それらが何であるか、またはどのように機能するかがわからないためです。 bbox_to_anchor()の最後の2つの数字はどういう意味ですか?

16
edesz

編集:

ImportanceOfBeingErnestからの回答を使用することを強くお勧めします。 凡例をプロットから外す方法

これは理解しやすいです:

import matplotlib.pyplot as plt
x = [1,2,3]
plt.subplot(211)
plt.plot(x, label="test1")
plt.plot([3,2,1], label="test2")
plt.legend(bbox_to_anchor=(0, 1), loc='upper left', ncol=1)
plt.show()

to座標(x、y)で遊んでください。 locには次を使用できます。

valid locations are:
right
center left
upper right
lower right
best
center
lower left
center right
upper left
upper center
lower center
25
Moritz

Bbox_to_anchorの引数は、Axes Coordinatesです。 matplotlibは、異なる座標系を使用して、画面上のオブジェクトの配置を容易にします。位置の凡例を処理する場合、処理する重要な座標系は、以下に示すように、Axes座標、Figure座標、およびDisplay座標(ピクセル単位)です。

matplotlib座標系

前述のように、bbox_to_anchorはAxes座標にあり、長方形の4つのTuple引数すべてを必要としません。 Axes座標に(xpos、ypos)を含む2つの引数のタプルを単に与えることができます。この場合のloc引数は、凡例のアンカーポイントを定義します。そのため、凡例を軸の右外側に固定し、上端に揃えるには、次を発行します。

lgd = plt.legend(bbox_to_anchor=(1.01, 1), loc='upper left')

ただし、これにより、Figureに対してAxesの位置が変更されることはありません。これにより、凡例がFigureキャンバスの外に配置されます。 Figureキャンバスを自動的に再配置して、軸と凡例に合わせて、次のアルゴリズムを使用しました。

まず、キャンバスに凡例を描画して、実際のピクセル座標を割り当てます。

plt.gcf().canvas.draw()

次に、ピクセル座標からFigure座標に移動する変換を定義します。

invFigure = plt.gcf().transFigure.inverted()

次に、ピクセル単位で凡例の範囲を取得し、Figure座標に変換します。 x方向の最も遠い範囲を引き出します。これは、調整する必要があるキャンバス方向です。

lgd_pos = lgd.get_window_extent()
lgd_coord = invFigure.transform(lgd_pos)
lgd_xmax = lgd_coord[1, 0]

軸についても同じことを行います。

ax_pos = plt.gca().get_window_extent()
ax_coord = invFigure.transform(ax_pos)
ax_xmax = ax_coord[1, 0]

最後に、凡例がキャンバス内に収まるように移動する必要がある軸の割合に合わせてtight_layoutを使用してFigureキャンバスを調整します。

shift = 1 - (lgd_xmax - ax_xmax)
plt.gcf().tight_layout(rect=(0, 0, shift, 1))

Tight_layoutのrect引数はFigure座標にあり、凡例を含まないAxesのtight_layout境界を含む長方形の左下隅と右上隅を定義することに注意してください。したがって、単純なtight_layout呼び出しは、(0、0、1、1)の四角形の境界を設定することと同等です。

4
Steve Horst