Matplotlib Legend:凡例の追加とカスタマイズの完全ガイド
Updated on
凡例のないグラフは、読者にどの線がどれなのかを推測させます。色を頭の中でマッチングし、データを誤読し、間違った結論を導きます。plt.legend()で凡例を追加するのは簡単ですが、どこに表示するか、どう見えるか、データを隠さないようにするかは、ほとんどのチュートリアルが示す以上の作業が必要です。
このガイドでは、基本的な凡例の作成から高度なカスタマイズまで、すべてをカバーします:プロット内外への配置、マルチカラムレイアウト、カスタムハンドル、複雑な図形の凡例。
基本的な凡例
自動ラベル
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
plt.plot(x, np.sin(x), label='sin(x)')
plt.plot(x, np.cos(x), label='cos(x)')
plt.legend()
plt.show()plot()のlabelパラメータが凡例に表示される内容を定義します。plt.legend()を呼び出して表示します。
オブジェクト指向スタイル
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(x, np.sin(x), label='sin(x)')
ax.plot(x, np.cos(x), label='cos(x)')
ax.legend()
plt.show()凡例の配置
locパラメータの使用
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(x, np.sin(x), label='sin(x)')
ax.plot(x, np.cos(x), label='cos(x)')
# 一般的な位置
ax.legend(loc='upper right') # デフォルト
# ax.legend(loc='upper left')
# ax.legend(loc='lower right')
# ax.legend(loc='lower left')
# ax.legend(loc='center')
# ax.legend(loc='best') # 重なりが最も少ない位置を自動選択
plt.show()すべてのlocオプション
| loc文字列 | loc数値 |
|---|---|
'best' | 0 |
'upper right' | 1 |
'upper left' | 2 |
'lower left' | 3 |
'lower right' | 4 |
'right' | 5 |
'center left' | 6 |
'center right' | 7 |
'lower center' | 8 |
'upper center' | 9 |
'center' | 10 |
bbox_to_anchorによる精密な配置
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(x, np.sin(x), label='sin(x)')
ax.plot(x, np.cos(x), label='cos(x)')
ax.plot(x, np.sin(x) + np.cos(x), label='sin(x) + cos(x)')
# 軸の割合座標(x, y)で凡例を配置
ax.legend(loc='upper left', bbox_to_anchor=(0.02, 0.98))
plt.show()プロット外の凡例
凡例がデータと重なる場合、外側に移動します:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
fig, ax = plt.subplots(figsize=(10, 5))
for i in range(6):
ax.plot(x, np.sin(x + i * 0.5), label=f'Phase {i}')
# プロットの右側に凡例を配置
ax.legend(loc='center left', bbox_to_anchor=(1.0, 0.5))
plt.tight_layout()
plt.show()import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
fig, ax = plt.subplots(figsize=(8, 6))
for i in range(5):
ax.plot(x, np.sin(x + i), label=f'Series {i+1}')
# プロットの下に凡例を配置
ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.1), ncol=5)
plt.tight_layout()
plt.show()凡例のスタイリング
フォントサイズとフレーム
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(x, np.sin(x), label='sin(x)')
ax.plot(x, np.cos(x), label='cos(x)')
ax.legend(
fontsize=12,
frameon=True, # 枠を表示(デフォルトTrue)
framealpha=0.8, # 枠の透明度
facecolor='lightyellow', # 背景色
edgecolor='gray', # 枠の色
shadow=True, # ドロップシャドウ
)
plt.show()マルチカラムレイアウト
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
fig, ax = plt.subplots(figsize=(10, 5))
for i in range(8):
ax.plot(x, np.sin(x + i * 0.4), label=f'Signal {i+1}')
# コンパクトな凡例のための4列
ax.legend(ncol=4, loc='upper center', fontsize=9)
plt.show()凡例のタイトル
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(x, x**2, label='Quadratic')
ax.plot(x, x**1.5, label='Power 1.5')
ax.plot(x, x, label='Linear')
ax.legend(title='成長モデル', title_fontsize=13, fontsize=11)
plt.show()カスタム凡例ハンドル
手動の凡例エントリ
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import matplotlib.lines as mlines
import numpy as np
fig, ax = plt.subplots(figsize=(8, 5))
# ラベルなしでプロット
ax.scatter(np.random.randn(50), np.random.randn(50), c='blue', s=20)
ax.scatter(np.random.randn(50) + 2, np.random.randn(50), c='red', s=20)
# カスタムハンドルを作成
blue_patch = mpatches.Patch(color='blue', label='グループA')
red_patch = mpatches.Patch(color='red', label='グループB')
line_handle = mlines.Line2D([], [], color='green', linestyle='--', label='閾値')
ax.legend(handles=[blue_patch, red_patch, line_handle])
plt.show()カラーマッピング付き散布図の凡例
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots(figsize=(8, 5))
categories = ['A', 'B', 'C']
colors = ['#e74c3c', '#3498db', '#2ecc71']
for cat, color in zip(categories, colors):
x = np.random.randn(30)
y = np.random.randn(30)
ax.scatter(x, y, c=color, label=f'カテゴリ {cat}', alpha=0.7, s=50)
ax.legend()
plt.show()凡例のカスタマイズオプション
| パラメータ | 説明 | 例 |
|---|---|---|
loc | 位置の文字列または数値 | 'upper right', 2 |
bbox_to_anchor | アンカーポイント (x, y) | (1.0, 0.5) |
ncol | 列数 | 3 |
fontsize | テキストサイズ | 12, 'small' |
title | 凡例のタイトル | 'My Legend' |
frameon | フレームを表示 | True, False |
framealpha | フレームの透明度 | 0.8 |
facecolor | 背景色 | 'white' |
edgecolor | 枠の色 | 'gray' |
shadow | ドロップシャドウ | True |
markerscale | マーカーサイズの倍率 | 1.5 |
labelspacing | エントリ間の垂直間隔 | 0.5 |
handlelength | 凡例線の長さ | 2.0 |
実践的な例
複数のプロットタイプの凡例
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(5)
values = [23, 45, 56, 78, 32]
trend = [20, 35, 50, 65, 40]
fig, ax = plt.subplots(figsize=(8, 5))
ax.bar(x, values, alpha=0.7, label='実績', color='steelblue')
ax.plot(x, trend, 'ro-', label='トレンド', linewidth=2)
ax.axhline(y=50, color='green', linestyle='--', label='目標')
ax.legend(loc='upper left')
ax.set_xlabel('四半期')
ax.set_ylabel('収益 ($K)')
plt.show()ツイン軸の個別凡例
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(2020, 2027)
revenue = [100, 120, 115, 140, 160, 175, 200]
employees = [50, 55, 52, 60, 70, 75, 85]
fig, ax1 = plt.subplots(figsize=(8, 5))
line1 = ax1.plot(x, revenue, 'b-o', label='収益 ($M)')
ax1.set_ylabel('収益 ($M)', color='blue')
ax2 = ax1.twinx()
line2 = ax2.plot(x, employees, 'r-s', label='従業員数')
ax2.set_ylabel('従業員数', color='red')
# 凡例を統合
lines = line1 + line2
labels = [l.get_label() for l in lines]
ax1.legend(lines, labels, loc='upper left')
plt.show()インタラクティブなデータ探索
グラフの見た目や凡例の配置を繰り返し調整する際、PyGWalker (opens in a new tab)を使えばJupyterで列をドラッグしてインタラクティブな可視化を構築できます——凡例、色、サイズは自動的に生成されます:
import pandas as pd
import pygwalker as pyg
df = pd.read_csv('your_data.csv')
walker = pyg.walk(df)よくある質問
Matplotlibのプロットに凡例を追加するには?
各plot()、scatter()、bar()呼び出しにlabel='name'を追加し、plt.legend()またはax.legend()を呼び出します。凡例は提供されたラベルを自動的に使用します。
凡例をプロットの外に移動するには?
bbox_to_anchorをlocと一緒に使用します。右側に配置:ax.legend(loc='center left', bbox_to_anchor=(1.0, 0.5))。下に配置:ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.1))。plt.tight_layout()を呼び出してクリッピングを防ぎます。
Matplotlibで凡例のフォントサイズを変更するには?
legend()にfontsizeを渡します:ax.legend(fontsize=14)または'small'、'medium'、'large'などの文字列サイズを使用します。タイトルの場合:ax.legend(title='Title', title_fontsize=16)。
複数列の凡例を作成するには?
ncolパラメータを使用します:ax.legend(ncol=3)で3列レイアウトを作成します。多くの凡例エントリがあり、コンパクトな水平レイアウトが必要な場合に便利です。
凡例の枠を削除するには?
frameon=Falseを設定します:ax.legend(frameon=False)。フレームを保持しつつ透明にするには、framealpha=0を使用します:ax.legend(framealpha=0)。
まとめ
Matplotlibの凡例はlabelパラメータとplt.legend()から始まります。標準的な位置にはlocを、プロット外に凡例を移動するにはbbox_to_anchorを、マルチカラムレイアウトにはncolを、カスタマイズにはfontsize、frameon、shadowなどのスタイリングパラメータを使用します。多くのシリーズがあるプロットでは、凡例を軸エリアの外に配置し、tight_layout()を呼び出してクリッピングを防ぎます。ツイン軸を持つ複雑な図形では、ラインハンドルを手動で結合して統一的な凡例を作成します。