Matplotlibの軸目盛とフォーマッター: 読みやすいスケールを作る
Updated on
目盛りが詰まり、日付が重なり、数字がバラバラだとプロットは読みにくくなります。Tickの位置(Locator)と表示方法(Formatter)を明示的に決めれば、軸がすっきりし、流れが伝わります。
LocatorとFormatterの使い分け
| 目的 | ツール | 例 |
|---|---|---|
| 一定間隔で置く | MultipleLocator | xを5刻み |
| 本数を制限 | MaxNLocator | yを6本以下 |
| 日付の目盛り | AutoDateLocator | 月/年を自動調整 |
| 自作ラベル | FuncFormatter | 単位やサフィックス追加 |
| ラベル回転 | tick_params(rotation=...) | 密な日付を45°に |
数値軸: 間隔と表示をそろえる
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator, FuncFormatter
import numpy as np
x = np.linspace(0, 50, 200)
y = np.log1p(x) * 3.2
fig, ax = plt.subplots(figsize=(7, 4))
ax.plot(x, y, color="tab:blue")
# xは10刻み、yは1.5刻み
ax.xaxis.set_major_locator(MultipleLocator(10))
ax.yaxis.set_major_locator(MultipleLocator(1.5))
# 単位付きラベル
ax.yaxis.set_major_formatter(FuncFormatter(lambda val, _: f"{val:.1f} dB"))
ax.set_xlabel("Samples")
ax.set_ylabel("Signal (dB)")
ax.grid(True, axis="both", linestyle="--", alpha=0.3)
plt.tight_layout()
plt.show()ポイント:
- 範囲が変わる場合は
MaxNLocator(nbins=6)で本数を制御。 - Formatterは位置を変えず、文字列だけを変える。
- 単位は軸ラベルかFormatterのどちらか1か所に。
日付軸: 重なりを防ぐ
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import pandas as pd
dates = pd.date_range("2024-01-01", periods=120, freq="D")
values = pd.Series(range(len(dates))).rolling(7, min_periods=1).mean()
fig, ax = plt.subplots(figsize=(8, 4))
ax.plot(dates, values, color="tab:green")
ax.xaxis.set_major_locator(mdates.MonthLocator(interval=1))
ax.xaxis.set_major_formatter(mdates.DateFormatter("%b %Y"))
ax.xaxis.set_minor_locator(mdates.WeekdayLocator(byweekday=mdates.MO, interval=2))
plt.setp(ax.get_xticklabels(), rotation=30, ha="right")
ax.set_ylabel("7-day avg")
ax.grid(True, which="both", axis="x", linestyle=":", alpha=0.4)
plt.tight_layout()
plt.show()ポイント:
- マイナー目盛り(例: 週ごと)で文脈を示しつつラベルは抑える。
- 日付ラベルは30–45°回転と
ha="right"で重なり防止。 - 時間幅が変わるなら
AutoDateLocator+ConciseDateFormatterを使う。
二軸の場合: 両方に設定
twinx/secondary_yaxis では各軸にLocatorとFormatterを設定し、色・単位・目盛りを揃える。凡例はセカンダリ軸記事の方法でまとめる。
トラブルシュート
- 目盛りが飛ぶ?
MultipleLocatorなど決定的なLocatorを指定。 - ラベルが切れる?
constrained_layout=Trueまたはplt.tight_layout(). - 本数が多い?
MaxNLocator(nbins=5)に下げるか、マイナーを消す (ax.tick_params(which="minor", length=0))。