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

如何获取划分双峰分布为三组的X分界值?代码结果不符预期求解

问题描述

需要将双峰分布划分为三组,预期分界值为x<5、5<x<90、x>90,但运行下方代码后未得到预期结果。

原代码

import numpy as np
from scipy.stats import gaussian_kde
from scipy.signal import find_peaks 

# Generate bimodal data
dist1 = np.random.normal(loc=0, scale=1, size=100) 
dist2 = np.random.normal(loc=90, scale=1, size=100)
bimodal = np.concatenate((dist1, dist2))

# Fit KDE 
kde = gaussian_kde(bimodal)
xgrid = np.linspace(0,100)
pdf = kde.evaluate(xgrid)

plt.hist(bimodal, bins=100, density=True)
plt.title("Bimodal distribution")

# Find peaks 
peaks, _ = find_peaks(pdf)
peak1, peak2 = xgrid[peaks]

# Find valley
pdf_min = np.min(pdf[(xgrid > peak1) & (xgrid < peak2)])
valley = xgrid[(pdf == pdf_min) & (xgrid > peak1) & (xgrid < peak2)]

# Create group labels
groups = np.ones(len(bimodal), dtype=int)
groups[bimodal < valley] = 0 
groups[(bimodal >= valley) & (bimodal <= peak1)] = 1
groups[bimodal > peak1] = 2

# Plot
plt.hist(bimodal)
plt.vlines([valley, peak1], 0, 100, colors='r')
plt.title("Bimodal distribution clustered into 3 groups")
plt.show()

print(groups)

问题分析与修正

原代码核心问题

  1. 缺失依赖导入:代码使用plt但未导入matplotlib.pyplot,会直接触发报错。
  2. 峰识别失效:find_peaks默认参数无法识别边缘峰(示例数据左峰在x=0附近,属于xgrid起始位置),导致无法正确获取两个峰的位置。
  3. 分组逻辑完全偏离预期:误将左峰位置作为右侧分界,且KDE谷值位于两个峰中间(约45左右),和预期的5、90分界完全不符。

修正方案

方案1:严格按预期阈值分组

如果直接使用你指定的5和90作为分界,无需依赖KDE计算峰谷,直接做阈值判断即可:

import numpy as np
import matplotlib.pyplot as plt

# 生成双峰数据
dist1 = np.random.normal(loc=0, scale=1, size=100) 
dist2 = np.random.normal(loc=90, scale=1, size=100)
bimodal = np.concatenate((dist1, dist2))

# 按预期阈值分组
groups = np.zeros(len(bimodal), dtype=int)
groups[(bimodal >= 5) & (bimodal <= 90)] = 1
groups[bimodal > 90] = 2

# 可视化结果
plt.hist(bimodal, bins=100, density=True)
plt.vlines([5, 90], 0, plt.ylim()[1], colors='r', linestyles='--')
plt.title("双峰分布分组结果(分界值:5、90)")
plt.show()

print(groups)

方案2:通过KDE自动适配数据分布分组

如果希望基于数据分布自动寻找类似分界(适配实际数据的峰谷特征),修正峰谷识别逻辑:

import numpy as np
from scipy.stats import gaussian_kde
import matplotlib.pyplot as plt

# 生成双峰数据
dist1 = np.random.normal(loc=0, scale=1, size=100) 
dist2 = np.random.normal(loc=90, scale=1, size=100)
bimodal = np.concatenate((dist1, dist2))

# 拟合KDE,扩展xgrid范围避免边缘峰被忽略
kde = gaussian_kde(bimodal)
xgrid = np.linspace(np.min(bimodal)-5, np.max(bimodal)+5, 500)
pdf = kde.evaluate(xgrid)

# 稳定获取两个峰的位置:取PDF的两个最大值点
peak_indices = np.argsort(pdf)[-2:]
peak_indices.sort()
peak_left, peak_right = xgrid[peak_indices]

# 查找两个峰之间的谷值
mask_between_peaks = (xgrid > peak_left) & (xgrid < peak_right)
valley_index = np.argmin(pdf[mask_between_peaks])
valley = xgrid[mask_between_peaks][valley_index]

# 自定义分界:左分界用预期的5,右分界用右峰位置
left_threshold = 5
right_threshold = peak_right

# 分组
groups = np.zeros(len(bimodal), dtype=int)
groups[(bimodal >= left_threshold) & (bimodal <= right_threshold)] = 1
groups[bimodal > right_threshold] = 2

# 可视化结果
plt.hist(bimodal, bins=100, density=True)
plt.vlines([left_threshold, right_threshold], 0, plt.ylim()[1], colors='r', linestyles='--')
plt.scatter([peak_left, peak_right], [pdf[peak_indices[0]], pdf[peak_indices[1]]], c='blue', label='峰')
plt.scatter(valley, pdf[mask_between_peaks][valley_index], c='green', label='谷')
plt.title("双峰分布自动分组结果")
plt.legend()
plt.show()

print(groups)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 23:21:11