matplotlib 如何让 colorbar 只显示整数刻度

最简且健壮的方法是使用 MaxNLocator(integer=True),它自动选择视觉舒适的整数刻度,适配动态数据范围和图窗缩放,避免手动设 ticks 的越界、坐标错位及不响应重绘等问题。

colorbar 刻度强制为整数的最简方法

直接用 plt.colorbar(..., ticks=range(int(vmin), int(vmax)+1)) 最快,但前提是数据范围不大、且你已知 vminvmax。更稳妥的做法是让 matplotlib 自动算出合适的整数刻度,避免硬编码。

  • 先获取当前 colorbar 的 ax(或通过 im.colorbar 拿到 Colorbar 对象)
  • 调用 cbar.set_ticks(np.arange(int(cbar.vmin), int(cbar.vmax)+1)),但注意:若 vmin/vmax 是浮点(比如 0.2–4.8),int()

    会截断,应改用 np.floornp.ceil
  • 更推荐用 MaxNLocator(integer=True),它能自动适配显示区域宽度,避免刻度挤成一团

用 MaxNLocator(integer=True) 控制 colorbar 刻度

这是最健壮的方式,尤其适合动态数据或不确定范围的图。它不强行塞满所有整数,而是选“视觉上舒服的整数位置”,同时严格保证每个 tick 都是整数。

  • 导入:from matplotlib.ticker import MaxNLocator
  • 画完 colorbar 后加一句:cbar.ax.yaxis.set_major_locator(MaxNLocator(integer=True))(竖直 colorbar)或 cbar.ax.xaxis.set_major_locator(...)(水平)
  • 如果想限制最多显示 6 个刻度,传参 MaxNLocator(integer=True, nbins=6)
  • 注意:该方式对极小范围(如 vmin=1.9, vmax=2.1)可能只显示一个 tick(2),这是正常行为,不是 bug

为什么 set_ticks([...]) 容易出错

手动传整数列表看似直接,但实际常踩三个坑:

  • 传入的 list 若超出 colorbar 数据范围(比如 vmin=0.5, vmax=3.2 却传 [0,1,2,3,4]),matplotlib 会静默忽略越界值,导致顶部/底部无刻度线
  • 若数据是 log scale 或自定义 norm,set_ticks 传的仍是数据值,但 colorbar 内部坐标已变换,容易错位
  • resize 图窗后,手动设置的 ticks 不会自动重排,而 MaxNLocator 会响应

完整可运行示例

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.ticker import MaxNLocator

data = np.random.randn(10, 10) * 2 + 1.5 # 均值约 1.5,范围大致 -2~5 im = plt.imshow(data, cmap='viridis') cbar = plt.colorbar(im)

关键:强制整数刻度

cbar.ax.yaxis.set_major_locator(MaxNLocator(integer=True))

plt.show()

这行 cbar.ax.yaxis.set_major_locator(...) 是核心,其余都是常规绘图。如果 colorbar 是水平的(orientation='horizontal'),把 yaxis 换成 xaxis 即可。

真正要注意的是:别在 plt.colorbar(..., ticks=[...]) 里硬写死列表,除非你确定数据范围永远不变;动态场景下,MaxNLocator(integer=True) 才是那个“设一次就忘掉”的解法。