Python仅用基础NumPy实现二维联合直方图替代histogram2d
NumPy手动实现二维联合直方图方案
要完全替代np.histogram2d得到一致输出,需要严格对齐NumPy官方的分箱、计数规则,全程仅使用NumPy基础函数即可实现,不需要依赖其他直方图相关内置接口。
核心实现逻辑
- 对齐官方参数规则:如果
bins传入单个整数,x、y两个维度使用相同的分箱数量 - 等宽分箱边界生成:用
np.linspace从样本最小值到最大值生成箱数+1个边界点,保证每个分箱宽度一致 - 索引计算:通过偏移+除法+向下取整得到每个样本点所属的分箱索引,单独处理最大值点,将其归入最后一个分箱(官方规则为最后一个分箱是双闭区间,其余分箱左闭右开)
- 向量化计数:用
np.add.at完成无冲突的分箱计数,避免遍历循环,保证计数结果和官方函数完全一致
可直接替换的实现代码
import numpy as np def manual_histogram2d(x, y, bins): # 处理bins参数:单整数则两维度分箱数一致 if np.isscalar(bins): x_bin_num = y_bin_num = bins else: x_bin_num, y_bin_num = bins # 生成和np.histogram2d完全一致的分箱边界 x_edges = np.linspace(x.min(), x.max(), x_bin_num + 1) y_edges = np.linspace(y.min(), y.max(), y_bin_num + 1) # 计算x维度分箱索引 x_width = x_edges[1] - x_edges[0] x_idx = np.floor((x - x_edges[0]) / x_width).astype(int) x_idx[x_idx == x_bin_num] = x_bin_num - 1 # 最大值归入最后一箱 # 计算y维度分箱索引 y_width = y_edges[1] - y_edges[0] y_idx = np.floor((y - y_edges[0]) / y_width).astype(int) y_idx[y_idx == y_bin_num] = y_bin_num - 1 # 最大值归入最后一箱 # 初始化计数矩阵并完成统计 hist_2d = np.zeros((x_bin_num, y_bin_num), dtype=np.intp) np.add.at(hist_2d, (x_idx, y_idx), 1) return hist_2d, x_edges, y_edges
替换使用方法
将原代码中调用np.histogram2d的部分替换为自定义函数即可,后续绘图逻辑不需要做任何修改:
from matplotlib.pyplot import imread import matplotlib.pyplot as plt Img1 = imread('img1.jpg') Img2 = imread('img2.jpg') # 替换原np.histogram2d调用 hist_2d, x_edges, y_edges = manual_histogram2d(Img1.ravel(), Img2.ravel(), bins=bins) plt.imshow(hist_2d.T, origin='lower')
你可以通过np.allclose对比手动实现和官方函数的三个返回值,结果会完全匹配。
内容的提问来源于stack exchange,提问作者stuckincode
相关产品推荐
相关产品推荐

