Python带权重直方图误差计算:如何获取sumw与sumw2?
好问题!确实,默认的numpy.histogram和plt.hist只返回每个区间的权重和(sumw),但想要计算泊松误差需要的权重平方和(sumw2),我们可以通过numpy的向量化操作来高效获取,不用像YODA那样逐个填充数据点。下面分两种场景给出解决方案:
使用numpy获取sumw和sumw2
我们可以先通过np.digitize确定每个数据点所属的直方图区间,再用np.bincount分别计算每个区间的权重和与权重平方和,步骤如下:
import numpy as np # 示例数据 x = np.random.normal(0, 1, 1000) # 随机数据 w = np.random.uniform(0.5, 1.5, 1000) # 对应权重 # 定义直方图分箱(和你后续绘图用的分箱保持一致) bins = np.linspace(-3, 3, 10) # 1. 获取每个数据点对应的箱索引 bin_indices = np.digitize(x, bins) # 2. 过滤掉超出分箱范围的数据点(这些点不会被计入直方图) valid_mask = (bin_indices > 0) & (bin_indices <= len(bins)-1) adjusted_indices = bin_indices[valid_mask] - 1 # 转换为从0开始的有效区间索引 # 3. 计算每个区间的sumw和sumw2 sumw = np.bincount(adjusted_indices, weights=w[valid_mask], minlength=len(bins)-1) sumw2 = np.bincount(adjusted_indices, weights=w[valid_mask]**2, minlength=len(bins)-1) # 验证:和numpy.histogram返回的sumw一致 n, _ = np.histogram(x, bins=bins, weights=w) print(np.allclose(sumw, n)) # 输出True,说明计算正确
使用matplotlib结合numpy获取sumw和sumw2
如果你已经用plt.hist绘制了直方图,只需要在绘图后补充计算sumw2即可,逻辑和上面一致:
import numpy as np import matplotlib.pyplot as plt # 示例数据 x = np.random.normal(0, 1, 1000) w = np.random.uniform(0.5, 1.5, 1000) bins = np.linspace(-3, 3, 10) # 绘制带权重的直方图,获取sumw(即返回的n) n, bins, patches = plt.hist(x, bins=bins, weights=w, alpha=0.7) # 计算sumw2 bin_indices = np.digitize(x, bins) valid_mask = (bin_indices > 0) & (bin_indices <= len(bins)-1) adjusted_indices = bin_indices[valid_mask] - 1 sumw2 = np.bincount(adjusted_indices, weights=w[valid_mask]**2, minlength=len(bins)-1) # 计算泊松误差并绘制 errors = np.sqrt(sumw2) # 用误差棒标注误差(直方图柱的中点作为x坐标) bin_centers = (bins[:-1] + bins[1:]) / 2 plt.errorbar(bin_centers, n, yerr=errors, fmt='none', capsize=3, color='red', label='Poisson Error') plt.legend() plt.show()
为什么这个方法比YODA更高效?
numpy的digitize和bincount都是向量化操作,底层用C实现,处理大数据量时比逐个填充数据点的循环快得多,完全不需要手动遍历每个数据点分配区间。
内容的提问来源于stack exchange,提问作者Lxndr
相关产品推荐
相关产品推荐

