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

如何编写带容差的函数查找连续函数/数组的第一、第二峰值

峰值查找函数实现方案

核心实现思路

  • 首先提取所有局部极大值作为候选峰值
  • 支持双维度容差过滤:
    • 数值容差:与更高峰值的差值小于该值的峰判定为噪声
    • 间距容差:与更高峰值的索引距离小于该值的峰判定为噪声
  • 过滤后按峰值从高到低排序,取前两位即为所需的第一、第二峰值

完整代码实现

import numpy as np
# 可选依赖scipy,如果不想引入可以用下方注释的原生实现替换候选点提取逻辑
from scipy.signal import argrelextrema

def peak(arr, tolerance):
    """
    查找数组的第一、第二峰值
    参数:
        arr: 输入一维numpy数组
        tolerance: 容差参数,可传入两种格式:
            1. 单个数值:仅作为数值容差,间距容差默认取数组长度的1/10
            2. 二元组(数值容差, 间距容差):分别设置数值和索引间距的过滤阈值
    返回:
        列表,每个元素为(峰值索引, 峰值数值),按峰值从高到低排序
    """
    # 解析容差参数
    if isinstance(tolerance, (int, float)):
        val_tol = tolerance
        dist_tol = len(arr) // 10
    else:
        val_tol, dist_tol = tolerance
    
    # 提取所有局部极大值点(比左右邻居都大的点)
    candidate_idx = argrelextrema(arr, np.greater)[0]
    # ---------------- 无scipy依赖的候选点提取替换逻辑 ----------------
    # candidate_idx = []
    # for i in range(1, len(arr)-1):
    #     if arr[i] > arr[i-1] and arr[i] > arr[i+1]:
    #         candidate_idx.append(i)
    # candidate_idx = np.array(candidate_idx)
    # -------------------------------------------------------------

    # 补充边界点判定:数组首尾如果是峰值的情况
    if len(arr) >=2 and arr[0] > arr[1]:
        candidate_idx = np.insert(candidate_idx, 0, 0)
    if len(arr) >=2 and arr[-1] > arr[-2]:
        candidate_idx = np.append(candidate_idx, len(arr)-1)
    
    # 按峰值从高到低排序候选点
    candidates = sorted([(idx, arr[idx]) for idx in candidate_idx], key=lambda x: -x[1])
    if not candidates:
        return []
    
    # 过滤噪声峰
    kept = [candidates[0]]
    for cur in candidates[1:]:
        cur_idx, cur_val = cur
        is_noise = False
        for k in kept:
            k_idx, k_val = k
            # 数值差小于容差 或者 距离小于容差,判定为噪声
            if (k_val - cur_val < val_tol) or (abs(cur_idx - k_idx) < dist_tol):
                is_noise = True
                break
        if not is_noise:
            kept.append(cur)
            # 已经找到前两个峰值可提前退出,提高性能
            if len(kept) >=2:
                break
    return kept

测试验证

测试用例1:无噪声的数组ar

ar = np.array([1,2,3,4,4.5,4.1,4.05,4,3,2,1,2,3,3.5,3.2,2,1,0])
print(peak(ar, tolerance=0.5))

输出结果:

[(4, 4.5), (13, 3.5)]

测试用例2:带小幅噪声的数组ar2

ar2 = np.array([1,2,3,4,4.5,4.1,4.2,4,3,2,1,2,3,3.5,3.2,2,1,0])
print(peak(ar2, tolerance=0.5))

输出结果和ar完全一致,索引6处的4.2因为和最高峰值4.5的差值仅0.3,小于设置的0.5数值容差,会被判定为噪声过滤:

[(4, 4.5), (13, 3.5)]

峰值效果示意图

峰值示意图

二维数组扩展思路

如果需要支持二维数组,可以将上述逻辑适配:

  1. 使用scipy.signal.argrelmax提取二维局部极大值点
  2. 容差逻辑增加二维坐标的欧氏距离作为间距容差判定标准
  3. 过滤后取前两位峰值即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 06:27:03