目录8
文章/Matplotlib/第 9 章
六边形分箱
Matplotlib · 第 9 / 43 章
628 字约 2 分钟
六边形分箱 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()
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=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 的和
这是 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。