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

如何获取两个sns.distplot的重叠面积?量化归一化分布差异

我来帮你搞定这个问题——既要算出两个KDE曲线的重叠面积,又要找个除了均值差之外的指标来量化分布差异,对吧?下面分两部分给你详细说明:

计算两个KDE曲线的重叠面积

Seaborn的distplot里的KDE是基于Scipy的gaussian_kde实现的,我们可以手动拟合KDE模型,然后通过积分计算重叠区域的面积。具体步骤如下:

  1. 分别拟合两个数据集的KDE模型
  2. 生成覆盖两个数据范围的密集x轴网格
  3. 计算每个x点对应的两个密度值
  4. 对每个x点取两个密度的最小值,再积分这个最小值曲线得到重叠面积

示例代码:

import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
from scipy.stats import gaussian_kde
from scipy.integrate import trapezoid

# 生成示例数据
x1 = np.random.normal(size=2000)
x2 = np.random.normal(size=1000) + 1

# 拟合KDE模型
kde1 = gaussian_kde(x1)
kde2 = gaussian_kde(x2)

# 生成统一的x轴范围(足够密集保证精度)
x_min = min(x1.min(), x2.min())
x_max = max(x1.max(), x2.max())
x_grid = np.linspace(x_min, x_max, 1000)

# 计算每个x点的密度值
pdf1 = kde1(x_grid)
pdf2 = kde2(x_grid)

# 提取重叠部分的密度值
overlap_pdf = np.minimum(pdf1, pdf2)

# 积分得到重叠面积
overlap_area = trapezoid(overlap_pdf, x_grid)

print(f"两个分布的KDE重叠面积:{overlap_area:.4f}")

# 可视化验证
sns.distplot(x1, hist=False, kde=True, color="r", kde_kws={"label": "x1"})
sns.distplot(x2, hist=False, kde=True, color="b", kde_kws={"label": "x2"})
plt.fill_between(x_grid, overlap_pdf, color='gray', alpha=0.5, label=f"Overlap Area: {overlap_area:.4f}")
plt.legend()
plt.show()

重叠面积的范围是0到1,值越接近1说明两个分布越相似,越接近0则差异越大。

除均值差外的分布差异度量

如果两个分布均值相同但形状差异大(比如一个正态、一个偏态),可以用这些非均值依赖的指标量化差异:

  • Kolmogorov-Smirnov检验(KS检验):衡量两个CDF曲线的最大垂直距离,范围0-1,值越大差异越显著。它是无参数检验,不依赖分布类型。
    代码示例:

    from scipy.stats import ks_2samp
    
    ks_stat, p_value = ks_2samp(x1, x2)
    print(f"KS检验统计量:{ks_stat:.4f},p值:{p_value:.4f}")
    

    说明:KS统计量越接近1,分布差异越大;p值小于0.05时,可拒绝“两个分布完全相同”的原假设。

  • Wasserstein距离(地球移动距离):衡量将一个分布转换为另一个所需的最小“工作量”,同时考虑位置和形状差异,对非正态分布友好。
    代码示例:

    from scipy.stats import wasserstein_distance
    
    wasserstein_dist = wasserstein_distance(x1, x2)
    print(f"Wasserstein距离:{wasserstein_dist:.4f}")
    

    说明:值越大表示两个分布的整体差异越大,比KS检验更能捕捉方差、偏度这类形状差异。

  • KL散度(Kullback-Leibler Divergence):衡量两个分布的信息差异,但它是不对称的(KL(P||Q)≠KL(Q||P)),使用时需注意方向。
    代码示例:

    # 计算KL散度:KL(x1分布 || x2分布)
    kl_div = trapezoid(pdf1 * np.log(pdf1 / pdf2), x_grid)
    print(f"KL散度(x1||x2):{kl_div:.4f}")
    

    说明:值越大表示从x2分布到x1分布的信息损失越大,若要对称衡量差异,可计算双向散度的平均值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:21:25