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

如何计算Python中两个直方图的相交区域面积

直方图重叠面积计算方案

你之前用同索引bin取最小值累加的思路本身没有问题,计算错误的核心原因是两个直方图没有使用完全一致的分箱规则。
当你分别对两个数据集调用plt.hist(..., bins=20)时,matplotlib会针对每个输入数据集单独计算分箱范围:取当前数据集的最小值作为分箱左边界、最大值作为分箱右边界,自动生成20个等宽bin。如果两个数据集的值域存在差异(尤其是包含负值、值域偏移较大时),两个直方图同索引的bin对应的数值区间完全不重合,这种情况下直接对同索引bin取最小值计算,结果必然错误。

实现逻辑

只要保证两个直方图使用完全相同的分箱边界,对应bin取最小值乘bin宽累加的逻辑对包含负值的数据集完全生效,具体步骤如下:

  • 先提取两个数据集的全局最小值、最大值,基于整体值域生成固定的20个等宽bin的边界数组
  • 用和matplotlib底层完全一致的numpy直方图计算接口,分别得到两个数据集在统一分箱下的密度值
  • 逐bin取两个密度的最小值,乘以bin宽度后累加,结果就是重叠区域的面积
  • 绘图时同样传入这套固定的bin边界,保证可视化结果和计算结果完全对应

可直接运行的代码示例

import numpy as np
import matplotlib.pyplot as plt

# 测试用例:特意构造包含负值的两个数据集
data1 = np.random.normal(loc=-2, scale=1.5, size=10000)
data2 = np.random.normal(loc=1, scale=2, size=10000)

# 生成统一分箱边界:20个bin对应21个边界点,覆盖两个数据集的全部值域
global_min = min(data1.min(), data2.min())
global_max = max(data1.max(), data2.max())
shared_bins = np.linspace(global_min, global_max, 21)

# 计算统一分箱下的密度直方图,density=True保证直方图总面积为1
hist_dens1, _ = np.histogram(data1, bins=shared_bins, density=True)
hist_dens2, _ = np.histogram(data2, bins=shared_bins, density=True)

# 计算重叠面积
bin_width = shared_bins[1] - shared_bins[0]
overlap_area = np.sum(np.minimum(hist_dens1, hist_dens2) * bin_width)
print(f"直方图重叠区域面积为: {overlap_area:.4f}")

# 绘图时复用同一套分箱,和计算逻辑保持一致
plt.hist(data1, bins=shared_bins, alpha=0.4, density=True, label='dataset1')
plt.hist(data2, bins=shared_bins, alpha=0.4, density=True, label='dataset2')
plt.legend()
plt.show()

注意事项

  • 无论计算还是绘图,都不要直接传bins=20让接口自动生成分箱,必须传入提前定义好的同一套bin边界数组
  • 计算时需要使用密度值(设置density=True),如果直接用原始计数,需要先将计数除以对应数据集的总样本量转换为频率,否则计算结果是重叠的样本数量而非面积
  • 该方案基于数值轴的绝对区间分箱,对全负值、全正值、正负值混合的数据集都能得到正确结果

内容的提问来源于stack exchange,提问作者Curious

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 03:06:09