Skip to content

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_anchorlocと一緒に使用します。右側に配置: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を、カスタマイズにはfontsizeframeonshadowなどのスタイリングパラメータを使用します。多くのシリーズがあるプロットでは、凡例を軸エリアの外に配置し、tight_layout()を呼び出してクリッピングを防ぎます。ツイン軸を持つ複雑な図形では、ラインハンドルを手動で結合して統一的な凡例を作成します。

📚