You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 05:06:48