如何从一维数据向量中提取模态峰值?
从一维数据的KDE曲线中提取模态峰值
给定如下数值列表,通过Pandas生成的核密度图(KDE)显示在约8和17的位置存在明显模态峰值:
import pandas as pd values = [ 8.42, 8.87, 8.88, 8.88, 8.88, 8.58, 8.58, 8.58, 8.58, 8.58, 8.58, 8.58, 8.58, 8.58, 0. , 8.58, 17.65, 17.65, 17.65, 17.65, 17.65, 17.65, 17.65, 17.65, 17.65, 17.65, 17.65, 17.65, 17.9 , 0. , 17.9 , 17.9 , 17.68, 17.68, 17.68, 17.68, 17.68, 17.68, 17.68, 17.68, 17.68, 17.68, 17.68, 8.89, 8.89, 9.86, 8. , 8.89, 8.89, 8.89, 8.93, 8.95, ] data = pd.Series(values) data.plot.kde()
要提取KDE曲线的模态峰值,需先生成KDE的离散数值点,再用scipy.signal.find_peaks检测峰值,具体步骤如下:
1. 导入依赖库
import numpy as np from scipy.stats import gaussian_kde from scipy.signal import find_peaks import matplotlib.pyplot as plt
2. 生成KDE密度曲线数据
先过滤原始数据中的0值(避免异常值干扰KDE计算),再生成KDE对象和对应的x/y轴数值:
# 过滤无效的0值 filtered_values = values[np.array(values) != 0] # 创建KDE对象,bw_method控制曲线平滑度,默认scott为经验值,也可手动设置数值(如0.5) kde = gaussian_kde(filtered_values, bw_method='scott') # 生成覆盖数据范围的密集x轴点,保证峰值检测精度 x = np.linspace(min(filtered_values), max(filtered_values), 1000) # 计算每个x对应的密度值 y = kde(x)
3. 检测KDE曲线的峰值
通过调整find_peaks的参数过滤噪声,得到准确的模态峰值:
# distance控制峰值间的最小距离,height过滤低高度的噪声峰,可根据实际曲线调整 peaks_idx, _ = find_peaks(y, distance=200, height=0.01) # 获取峰值对应的x轴数值(即模态位置) peak_values = x[peaks_idx] print("检测到的模态峰值:", peak_values)
4. 可视化验证
将直方图、KDE曲线和检测到的峰值画在一起,确认结果:
plt.hist(filtered_values, bins=30, density=True, alpha=0.3, label='直方图') plt.plot(x, y, label='KDE曲线') plt.scatter(peak_values, y[peaks_idx], color='red', s=50, label='检测到的峰值') plt.legend() plt.show()
关键说明
- 异常值处理:原始数据中的0属于异常值,会干扰KDE计算和峰值检测,建议提前剔除。
- 带宽调整:
bw_method参数决定曲线平滑度,数值越小曲线越尖锐,可能检测到更多小峰值;数值越大曲线越平滑,可能合并相近峰值。 - 参数适配:
find_peaks的distance和height需根据KDE曲线的实际形态调整,确保过滤掉无关的噪声峰。
内容的提问来源于stack exchange,提问作者Peter Prescott
相关产品推荐
相关产品推荐

