numpy/matplotlib中对数分箱直方图轮廓绘制错位解决方法
问题描述
使用numpy.hist2d完成对数空间等宽分箱(分箱边界通过numpy.logspace生成)后叠加轮廓图时,会出现两类异常:
- 轮廓位置与x/y维度的实际数据点位置不匹配
- 二维直方图与绘制的轮廓完全无法重叠
轮廓实际按照线性空间的物理绘图位置放置,没有匹配对数坐标轴下的对应坐标,异常效果如下:
最小复现代码
import numpy as np import matplotlib.pyplot as plt x = np.random.normal(loc=500, scale=100,size=10000) y = np.random.normal(loc=600, scale=60, size=10000) nbins = 50 bins = (np.logspace(np.log10(10),np.log10(1000),nbins),np.logspace(np.log10(10),np.log10(1000),nbins)) HH, xe, ye = np.histogram2d(x,y,bins=bins) plt.hist2d(x,y,bins=bins,cmin=1); grid = HH.transpose() extent = np.array([xe.min(), xe.max(), ye.min(), ye.max()]) cs = plt.contourf(grid,2,extent=extent,extend='max',cmap='plasma',alpha=0.5,zorder=100) plt.contour(grid,2,extent=extent,colors='k',zorder=100) plt.yscale('log') plt.xscale('log')
问题根源
plt.contour/plt.contourf仅传入网格数组和extent参数时,会默认网格点在extent划定的坐标范围内线性均匀分布。但对数分箱的边界在线性坐标下是不等距的(数值越大,分箱间隔越宽),直接用extent映射会把不等距的分箱统计结果强行拉伸到线性均匀网格上,和按实际分箱边界绘制的hist2d结果自然错位。
修复方案
不要依赖extent做非均匀网格的坐标映射,先计算每个分箱的中心坐标,生成对应坐标网格后显式传入轮廓绘制接口,让接口明确每个网格点对应的实际坐标位置,即可实现完美对齐。
修复后的可运行代码:
import numpy as np import matplotlib.pyplot as plt rng = np.random.default_rng(42) # 固定随机种子便于复现 x = rng.normal(loc=500, scale=100, size=10000) y = rng.normal(loc=600, scale=60, size=10000) nbins = 50 # 生成对数分箱边界 bins = ( np.logspace(np.log10(10), np.log10(1000), nbins), np.logspace(np.log10(10), np.log10(1000), nbins) ) # 计算二维直方图 HH, xe, ye = np.histogram2d(x, y, bins=bins) # 绘制二维直方图底图 plt.hist2d(x, y, bins=bins, cmin=1, zorder=1) # 计算每个分箱的中心坐标,生成轮廓用的坐标网格 x_centers = (xe[:-1] + xe[1:]) / 2 y_centers = (ye[:-1] + ye[1:]) / 2 X, Y = np.meshgrid(x_centers, y_centers) grid = HH.T # histogram2d输出维度为(x_bin_num, y_bin_num),转置匹配contour的维度要求 # 显式传入坐标网格绘制轮廓,无需再传extent参数 plt.contourf(X, Y, grid, levels=2, extend='max', cmap='plasma', alpha=0.5, zorder=10) plt.contour(X, Y, grid, levels=2, colors='k', zorder=11) # 设置对数坐标轴 plt.xscale('log') plt.yscale('log') plt.show()
关键注意点
- 所有非均匀间隔的分箱(包括对数分箱、自定义不等距分箱)绘制轮廓时,都不能仅靠
extent映射坐标,必须显式传入网格点的实际坐标 numpy.histogram2d返回的统计矩阵维度顺序和contour要求的Z矩阵维度顺序不一致,必须做转置- 分箱中心取相邻两分箱边界的平均值即可,和
hist2d绘制的色块中心位置完全对齐
内容的提问来源于stack exchange,提问作者Austincv
相关产品推荐
相关产品推荐

