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

如何统计从0起始并回落至0的峰值?Python find_peaks用法

解决Scipy find_peaks统计“从0起始并回落至0”峰值的问题

find_peaks的内置参数无法直接过滤出“必须从0起始、之后回落至0”的峰值,因为它仅关注峰值自身的局部特征(高度、突出度等),不校验峰值前后序列是否回到基线(0)。需要通过额外的过滤逻辑实现需求,具体步骤如下:


1. 先找出所有基线(0)的位置

由于浮点精度问题,避免直接判断array == 0,用小阈值识别接近0的点:

import numpy as np
zero_indices = np.where(np.abs(array) < 1e-6)[0]

2. 编写过滤函数验证峰值的前后基线

对每个候选峰值,检查其前后是否存在0点,确保峰值是“从0升起、回落至0”的独立峰:

def filter_valid_peaks(candidate_peaks):
    valid_peaks = []
    for peak in candidate_peaks:
        # 找峰值前最近的0点
        prev_zero = zero_indices[zero_indices < peak][-1] if len(zero_indices[zero_indices < peak]) > 0 else -1
        # 找峰值后最近的0点
        next_zero = zero_indices[zero_indices > peak][0] if len(zero_indices[zero_indices > peak]) > 0 else len(array)
        
        # 验证逻辑:
        # - 峰值前后都有0点,说明是完整的“0-峰值-0”区间
        # - 若为最后一个峰值,需确认序列末尾已回落至0
        if prev_zero != -1 and next_zero != len(array):
            valid_peaks.append(peak)
        elif next_zero == len(array) and np.abs(array[-1]) < 1e-6:
            valid_peaks.append(peak)
    return np.array(valid_peaks)

3. 结合原代码实现过滤

先获取候选峰值,再用过滤函数筛选有效峰值:

from scipy.signal import find_peaks
import matplotlib.pyplot as plt

# 获取原候选峰值
peaks1_candidate = find_peaks(array, height=(1,1.5), prominence=1)[0]
peaks1_5_candidate = find_peaks(array, height=(1.5,2), prominence=1.5)[0]
peaks2_candidate = find_peaks(array, height=2, prominence=2)[0]

# 过滤有效峰值
peaks1 = filter_valid_peaks(peaks1_candidate)
peaks1_5 = filter_valid_peaks(peaks1_5_candidate)
peaks2 = filter_valid_peaks(peaks2_candidate)

# 绘图代码不变
fig, ax = plt.subplots(figsize=(30, 10), dpi=80)
plt.plot(spi_neg['date'], spi["SPI-12"])
[plt.axvline(spi_neg.date.iloc[p], c='red', linewidth=0.3) for p in peaks1]
[plt.axvline(spi_neg.date.iloc[p], c='green', linewidth=0.3) for p in peaks1_5]
[plt.axvline(spi_neg.date.iloc[p], c='purple', linewidth=0.3) for p in peaks2]
plt.axhline(2, linestyle='dashed', linewidth=1)
plt.axhline(1.5, linestyle='dashed', linewidth=1)
plt.axhline(1, linestyle='dashed', linewidth=1)
plt.show()

可选优化:严格校验上升/下降趋势

如果需要确保峰值是从0上升到峰值,再下降回0,可以在过滤函数中添加趋势判断:

# 在filter_valid_peaks函数的if判断内添加:
# 检查从prev_zero到peak是上升趋势(非递减)
is_rising = np.all(array[prev_zero:peak+1] >= array[prev_zero:peak])
# 检查从peak到next_zero是下降趋势(非递增)
is_falling = np.all(array[peak:next_zero+1] <= array[peak:next_zero])
if is_rising and is_falling:
    valid_peaks.append(peak)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 03:45:41