Matplotlib 轴刻度与格式化:让刻度可读可控
Updated on
刻度拥挤、日期重叠、数字杂乱会让图表难以阅读。明确指定刻度位置(Locator)和显示方式(Formatter),就能让每条轴讲清楚故事。
Locator vs 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 之一,避免重复。
日期轴:避免重叠
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,保证颜色、刻度和单位一致。图例的整理可参考双轴指南。
快速排查
- 刻度跳动?设定确定性 locator(如
MultipleLocator)。 - 标签被裁剪?启用
constrained_layout=True或plt.tight_layout()。 - 刻度太多?降到
MaxNLocator(nbins=5)或隐藏次刻度 (ax.tick_params(which="minor", length=0))。