Skip to content
トピック
Matplotlib
Matplotlib 凡例を外側に置く:bbox_to_anchor 早見表

Matplotlib 凡例を外側に置く:bbox_to_anchor 早見表

公開日

更新日

bbox_to_anchor と loc で Matplotlib の凡例を軸の外へ。右・左・下への配置、必要なら軸を縮め、bbox_inches='tight' で保存時に切れないようにする。

既定の凡例は 軸の内側 に乗り、データに被りがちです。外側に置くには、loc(凡例ボックスのどの角をアンカーにするか)と bbox_to_anchor(そのアンカーを軸座標のどこに置くか)をセットで使います。

クイックフィックス

import matplotlib.pyplot as plt
import numpy as np
 
x = np.linspace(0, 10, 200)
fig, ax = plt.subplots()
ax.plot(x, np.sin(x), label="sin(x)")
ax.plot(x, np.cos(x), label="cos(x)")
 
# Outside, upper-right of the axes
ax.legend(bbox_to_anchor=(1.02, 1), loc="upper left", borderaxespad=0)
 
plt.tight_layout()
plt.show()
配置典型的な呼び出し
軸の右legend(bbox_to_anchor=(1.02, 1), loc="upper left")
右・上下中央legend(loc="center left", bbox_to_anchor=(1.02, 0.5))
下・横並びlegend(loc="upper center", bbox_to_anchor=(0.5, -0.12), ncol=n)
legend(loc="lower center", bbox_to_anchor=(0.5, 1.02), ncol=n)
切れないエクスポートsavefig(..., bbox_inches="tight") または tight_layout() / constrained_layout=True

軸座標: (0, 0) は軸の左下、(1, 1) は右上。1 を少し超える、または 0 を少し下回る値は、枠のすぐ外側です。

問題: 凡例がデータに被る

fig, ax = plt.subplots(figsize=(7, 4))
ax.plot(x, np.sin(x), label="sin(x)", lw=2)
ax.plot(x, np.cos(x), label="cos(x)", lw=2)
ax.legend(loc="best")  # still inside the axes
ax.set_title("Default legend (often overlaps data)")
plt.show()

Default Matplotlib legend inside the axes

loc="best"内側 のいちばんマシな角を選ぶだけです。図の余白へ凡例を出してはくれません。

bbox_to_anchor と loc の役割分担

  1. bbox_to_anchor=(x, y) — 既定では軸の割合座標での点。
  2. loc="upper left" など凡例ボックス上のどの点がそのアンカーにピン留めされるか。
  3. borderaxespad — 軸と凡例の余白。外側にきっちり寄せるなら 0

頭の中のモデル: プロット上のアンカー点 + 凡例のどの角をその点に乗せるか

凡例を右に置く

fig, ax = plt.subplots(figsize=(7, 4))
ax.plot(x, np.sin(x), label="sin(x)", lw=2)
ax.plot(x, np.cos(x), label="cos(x)", lw=2)
ax.legend(bbox_to_anchor=(1.02, 1), loc="upper left", borderaxespad=0)
ax.set_title("Legend outside: upper right of axes")
fig.tight_layout()
plt.show()

Legend placed outside to the right of the axes

ウィンドウでもまだ切れるなら、tight_layout() / subplotsconstrained_layout=True、または次節のように軸を縮めて余白を確保します。

軸を縮めてから凡例をドックする

系列が多いときは、凡例専用の列を残します。

x = np.arange(10)
fig = plt.figure(figsize=(7.2, 4.2))
ax = fig.add_subplot(111)
 
for i in range(5):
    ax.plot(x, i * x, label=f"y = {i}x", lw=2)
 
# Leave ~22% of the figure width for the legend
box = ax.get_position()
ax.set_position([box.x0, box.y0, box.width * 0.78, box.height])
ax.legend(loc="center left", bbox_to_anchor=(1.02, 0.5), borderaxespad=0)
ax.set_title("Shrink axes, legend to the right")
plt.show()

Axes shrunk with legend docked on the right

最近の代替: 外側の artist と相性の良いレイアウトエンジンで figure を作ります。

fig, ax = plt.subplots(layout="constrained")
# ... plot ...
ax.legend(bbox_to_anchor=(1.02, 1), loc="upper left")

プロットの下に横並び凡例

ncol で 1 行に並べ、チャート下に置きます。スライドや横長ダッシュボード向きです。

x = np.arange(10)
fig = plt.figure(figsize=(7.2, 4.4))
ax = fig.add_subplot(111)
 
for i in range(5):
    ax.plot(x, i * x, label=f"y = {i}x", lw=2)
 
box = ax.get_position()
ax.set_position([box.x0, box.y0 + box.height * 0.12, box.width, box.height * 0.88])
ax.legend(loc="upper center", bbox_to_anchor=(0.5, -0.12), ncol=5)
ax.set_title("Horizontal legend below the plot")
plt.show()

Horizontal legend placed below the plot

判断ガイド

状況優先する手段
系列 2–4、単純な折れ線bbox_to_anchor=(1.02, 1), loc="upper left" + tight_layout()
系列が多くレイアウトを安定させたい軸を縮める / layout="constrained" + 右側凡例
横長の図 / プレゼン下側凡例 + ncol
地図や画像で箱が邪魔妥協として内側半透明: framealpha=0.3
論文用 PNG/PDF必ず bbox_inches="tight" を試す(次節)

エクスポートの罠: 外側凡例がファイルで消える

対話ウィンドウでは見えるのに、savefig で切れることがあります。定番の直し方:

fig, ax = plt.subplots(figsize=(7, 4))
ax.plot(x, np.sin(x), label="sin(x)", lw=2)
ax.plot(x, np.cos(x), label="cos(x)", lw=2)
ax.legend(bbox_to_anchor=(1.02, 1), loc="upper left", borderaxespad=0)
ax.set_title("Outside legend kept with bbox_inches='tight'")
 
fig.savefig("legend-outside.png", dpi=150, bbox_inches="tight", facecolor="white")

Saved figure that keeps the outside legend via bbox_inches tight

詳しくは savefig でラベルが切れる。ラベルがまだぶつかるなら、アンカーの微調整より先に 図サイズ を上げます。

ボックスを動かさない追加コントロール

ax.legend(
    bbox_to_anchor=(1.02, 1),
    loc="upper left",
    borderaxespad=0,
    frameon=True,
    fancybox=False,
    framealpha=0.95,
    fontsize=9,          # or prop={"size": 9}
    title="Series",
    alignment="left",
)
  • ncol — 複数列の凡例
  • framealpha — データ上にどうしても残すときの透明度
  • title — 複数系列のグループ見出し

位置以外の凡例スタイル全般は Matplotlib legend を参照してください。

よくある罠

見える症状直し方
loc="right" だけ凡例がまだ内側1.0 を超える bbox_to_anchor が必要
GUI では外側、PNG では無いエクスポートでクリップbbox_inches="tight" または constrained layout
誤ってデータ座標の bbox_to_anchor凡例が飛んでいく既定は軸座標。意図がない限り 2 タプルで、Bbox は使わない
凡例フォントが巨大図を支配するfontsize=8–10、または列を減らす
colorbar と重なる余白が潰れる両方にスペースを取る、または凡例を下へ

FAQ

まとめ

外側凡例は謎 API ではなくレイアウト問題です。loc で凡例の角をピン留めし、bbox_to_anchor でそのピンを軸のすぐ外(> 1 または < 0)に置き、エクスポートでは tight / constrained で余白がファイルに残るようにします。系列が多いときは右側スタック、横長の図では下側の ncol 行が向いています。

関連ガイド