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

如何识别数据中的显著峰值?现有Python函数存在峰值识别偏差

修正scipy.signal峰值识别误判单个点的方案

问题根源

你用scipy.signal.find_peaks实现的峰值识别,默认仅判断局部极值点,未对峰值的连续性/宽度做约束,同时没结合你定义的“显著峰值(其他峰值功率不超其10%)”规则,导致单个噪声点或孤立极值被误判为有效峰值。

具体修正步骤

1. 给峰值添加宽度约束

使用find_peaks的width参数强制要求峰值覆盖足够多的数据点,配合rel_height定义峰值的相对高度阈值,过滤窄尖峰:

from scipy.signal import find_peaks

# 示例:要求峰值宽度至少3个数据点,相对高度0.5(峰值两侧下降到一半高度的跨度)
peaks, properties = find_peaks(spectral_power, width=3, rel_height=0.5)

注:width的数值可根据你的数据密度调整,比如数据采样率高就设更大值

2. 提取完整峰值段的功率数据

通过properties返回的left_bases和right_bases,获取每个峰值的左右基线位置,进而提取该峰值对应的完整数据段(而非单个极值点):

peak_segments = []
# 遍历每个峰值的左右基线,截取完整峰值区间
for left, right in zip(properties['left_bases'], properties['right_bases']):
    peak_segment = spectral_power[int(left):int(right)+1]
    peak_segments.append(peak_segment)

3. 筛选符合定义的显著峰值

计算每个完整峰值段的最大功率(或平均功率,按需选择),然后筛选出满足“其他峰值功率不超过其10%”的显著峰值:

# 计算每个峰值段的最大功率
peak_max_powers = [max(seg) for seg in peak_segments]

# 筛选显著峰值
significant_peaks = []
for idx, main_power in enumerate(peak_max_powers):
    # 检查所有其他峰值的功率是否≤当前峰值的10%
    is_significant = all(other_power <= 0.1 * main_power for j, other_power in enumerate(peak_max_powers) if j != idx)
    if is_significant:
        # 存储峰值位置和对应的完整段数据
        significant_peaks.append((peaks[idx], peak_segments[idx]))

4. 可选:预处理平滑数据

若原始数据噪声较多,先做平滑处理减少孤立极值点:

import numpy as np

# 滚动平均平滑(窗口大小5,可调整)
smoothed_power = np.convolve(spectral_power, np.ones(5)/5, mode='same')
# 用平滑后的数据执行峰值识别
peaks, properties = find_peaks(smoothed_power, width=3, rel_height=0.5)

测试建议

用你的两组数据集验证:

  • 调整width参数找到适合你数据的最小峰值宽度
  • 确认显著峰值筛选逻辑符合你的定义
  • 对比修正前后结果,确保单个数据点的误判被完全过滤

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 22:00:53