目录8

文章Matplotlib第 9 章

六边形分箱

Matplotlib · 第 9 / 43 章

六边形分箱 hexbin()

hist2d 的「圆润版」:网格从方格换成六边形,斜向拼接更均匀,视觉上比方格更接近等距。

更重要的是它多了一个 C 参数——可以按第三个变量聚合,而不是只数点数。这一点是 hist2d 做不到的。

Python19 行
Axes.hexbin(
    x, y,                # 坐标,一维等长
    C=None,              # 聚合用的第三变量;不传就只计数
    gridsize=100,        # 六边形数量;int 或 (nx, ny)
    bins=None,           # 'log' / int / 边界序列,控制色阶分档
    xscale='linear',     # 'linear' / 'log'
    yscale='linear',
    extent=None,         # (xmin, xmax, ymin, ymax) 统计范围
    cmap=None,
    norm=None,           # LogNorm() 常用
    vmin=None, vmax=None,
    alpha=None,
    linewidths=None,
    edgecolors='face',   # 默认与填充同色,看不出缝
    reduce_C_function=np.mean,   # C 的聚合方式
    mincnt=None,         # 计数低于此值的格子不画
    marginals=False,     # True 时四周加 1D 边缘分布
    **kwargs
)
参数 一句话 默认值的影响
gridsize 六边形密度 默认 100 偏细,常用 20~40
C 第三变量 不传 = 数点数
reduce_C_function C 怎么聚合 默认 np.mean,可换 np.sum / np.max / np.median
mincnt 最小计数 低于此值不画(含空格子)
marginals 边缘分布 True 时四周多出 1D 直方图
edgecolors 边线 默认 'face';改 "white" 才能看到六边形轮廓

最小示例

Python8 行
rng = np.random.default_rng(42)
x = rng.normal(0, 1, 8000)
y = rng.normal(0, 1, 8000)

fig, ax = plt.subplots()
hb = ax.hexbin(x, y, gridsize=30, cmap="Blues")
fig.colorbar(hb, ax=ax, label="计数")
plt.show()

5000 个点、gridsize=30 的六边形分箱

gridsize:默认 100 太细

Python4 行
ax.hexbin(x, y, gridsize=10)      # 很粗,适合看大趋势
ax.hexbin(x, y, gridsize=30)      # 常用
ax.hexbin(x, y, gridsize=60)      # 很细,接近散点
ax.hexbin(x, y, gridsize=(40, 20))  # 两向分开给

gridsize 10 / 30 / 60 的对比

gridsize=100(默认)在几千个点的数据上会得到大量空格子,看起来像噪声。除非数据量上万,否则都该显式调小。

mincnt:空桶不画

Python1 行
ax.hexbin(x, y, gridsize=30, mincnt=1)     # 计数为 0 的六边形不画

不设 mincnt 时,空格子会画成色阶的最低色(通常是浅色),整张图有一层“灰色背景”。mincnt=1 直接抹掉,轮廓立刻清楚。

C 与 reduce_C_function:按第三变量聚合(重点)

Python6 行
z = np.hypot(x, y)

ax.hexbin(x, y, gridsize=30)                                   # 颜色 = 格内点数
ax.hexbin(x, y, C=z, gridsize=30, cmap="magma")                 # 颜色 = 格内 z 的均值
ax.hexbin(x, y, C=z, gridsize=30, reduce_C_function=np.max)     # 颜色 = 格内 z 的最大值
ax.hexbin(x, y, C=z, gridsize=30, reduce_C_function=np.sum)     # 颜色 = 格内 z 的和

不传 C(计数)、传 C(均值)、传 C + 取最大

这是 hexbin 比 hist2d 强的地方:同一张图上可以同时表达「点在哪」和「那里的某个值是多少」。典型场景:

想看什么 写法
每个区域多少笔交易 不传 C(计数)
每个区域的平均客单价 C=金额(默认均值)
每个区域的最大单笔 C=金额, reduce_C_function=np.max
每个区域的总销售额 C=金额, reduce_C_function=np.sum

默认是均值,这一点最容易记错。 想求和必须显式写 np.sum,否则颜色是平均值——两次运行数据量不同也看不出来。

marginals:四边带边缘分布

Python1 行
ax.hexbin(x, y, gridsize=30, marginals=True)

打开后上下左右各多出一条 1D 直方图,一眼能看出两个方向各自的分布形状。适合做「联合分布 + 边缘分布」图,省掉手动拆子图。代价是布局会变,set_xlim 之类要按整体算。

返回对象

Python11 行
hb = ax.hexbin(x, y, gridsize=30)
fig.colorbar(hb, ax=ax)              # 直接传,不用取索引

hb.get_offsets()                     # M×2:M 个六边形中心的 (x, y)
hb.get_array()                       # M 个六边形的值(计数或聚合结果)
hb.get_clim()                        # (vmin, vmax) 当前色阶
hb.set_clim(0, 200)                  # 改色阶
hb.set_cmap("viridis")               # 改配色

i = int(np.argmax(hb.get_array()))   # 反查「最密六边形」中心
print("最密处:", hb.get_offsets()[i])

hexbin 返回的是 PolyCollection,不是数组。它能直接传给 colorbar(不像 hist2d 要取 mesh),但拿不到计数矩阵——想要数值就改用 np.histogram2d 或 hist2d。

注意事项

  • gridsize 默认 100,几千个点时过细,看起来像噪点。
  • reduce_C_function 默认是 np.mean 不是 np.sum。
  • mincnt 不设时,空格子会占据色阶最低色。
  • edgecolors 默认 'face',所以六边形之间看不出缝;要网格感就改 "white"。
  • hexbin 返回 PolyCollection,hist2d 返回 QuadMesh,两者传 colorbar 的方式不同。
  • 六边形分箱不能像 hist2d 那样直接给出计数矩阵,要数值请用 np.histogram2d。