Matplotlibのセカンダリ軸: twinxとsecondary_yaxisの使い分け
Updated on
1つのプロットで2つのスケールが必要なとき(ドルと個数、摂氏と華氏など)、軸を誤って追加すると読み手を誤解させます。ずれた目盛り、合わない凡例、切れたラベルがよくある問題です。正しい二軸ツールを選び、明確な変換を入れるだけでスケールの整合性を守れます。
すぐ決めるための表
| アプローチ | 使う場面 | 長所 | 注意点 |
|---|---|---|---|
twinx / twiny | x(またはy)位置を共有する別の系列を重ねたい | シンプルで速い | 目盛りの書式は手動、スケールは自動同期しない |
secondary_yaxis / secondary_xaxis | 2系列が変換可能(例: °C ↔ °F) | 順変換/逆変換で目盛りを確実に整列 | 正確な変換が必須、単調な変換のみ |
| 共有軸のサブプロット2枚 | 重ねずに比較させたい | 視覚的にクリア | スペースが必要、凡例は別々 |
レシピ: twinxで2つのy軸
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(1, 13)
sales = np.array([12, 18, 25, 30, 28, 35, 40, 38, 32, 28, 22, 18])
customers = np.array([120, 155, 180, 210, 205, 230, 245, 240, 225, 200, 175, 150])
fig, ax = plt.subplots(figsize=(8, 4))
ax.plot(x, sales, color="tab:blue", label="Sales (k$)")
ax.set_xlabel("Month")
ax.set_ylabel("Sales (k$)", color="tab:blue")
ax.tick_params(axis="y", labelcolor="tab:blue")
ax2 = ax.twinx()
ax2.plot(x, customers, color="tab:orange", label="Customers")
ax2.set_ylabel("Customers", color="tab:orange")
ax2.tick_params(axis="y", labelcolor="tab:orange")
lines = ax.get_lines() + ax2.get_lines()
labels = [line.get_label() for line in lines]
ax.legend(lines, labels, loc="upper left")
plt.tight_layout()
plt.show()ポイント:
- 軸ごとに色を分けて凡例の混乱を防ぐ。
- 両軸のラインを集めてから
legendを呼ぶ。 tight_layout()やconstrained_layout=Trueでラベル欠けを防止。
レシピ: secondary_yaxisで安全な変換
import matplotlib.pyplot as plt
import numpy as np
temps_c = np.linspace(-20, 40, 200)
fig, ax = plt.subplots(figsize=(7, 4))
ax.plot(temps_c, np.sin(temps_c / 10), color="tab:blue", label="Signal vs °C")
ax.set_xlabel("Temperature (°C)")
ax.set_ylabel("Signal")
def c_to_f(c):
return c * 9/5 + 32
def f_to_c(f):
return (f - 32) * 5/9
ax_f = ax.secondary_xaxis("top", functions=(c_to_f, f_to_c))
ax_f.set_xlabel("Temperature (°F)")
ax.legend(loc="lower right")
plt.tight_layout()
plt.show()ポイント:
- 必ず順変換と逆変換の両方を渡し、目盛りを揃える。
- 単調で逆変換可能な変換だけを使う。
- 目盛りの書式 (
ax_f.xaxis.set_major_formatter("{x:.0f}°F")) で単位を明確に。
スケールを正しく保つ
- 無関係な系列なら二軸を避け、別サブプロットの方が分かりやすい。
- 片方が圧倒的なら正規化してから比較する。
- グリッドは主軸だけに出して視覚ノイズを下げる。
トラブルシューティング
- 凡例が重複? 両軸のラインをまとめて
legend。 - ラベルが切れる?
constrained_layout=Trueかplt.tight_layout()。 - 目盛り色が合わない? 両方の軸で
tick_params(labelcolor=...)を設定。