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

基于Python Pandas识别不同周期的局部极值以定位峰值关键节点

解决DataFrame周期内局部极值定位问题及Series标签不匹配错误

首先,咱们拆解你遇到的两个核心问题:一是最初用全局最值标记A/B点不符合预期,二是尝试局部极值时抛出的ValueError: Can only compare identically-labeled Series objects错误。

错误原因分析

你第二次代码里的问题出在这行逻辑:

g.Value[(g.Value.shift(10) < g.Value) & (g.Value.shift(-10) < g.Value)]

筛选后的Series只保留了符合局部极值条件的行,它的索引和原g['Value']的索引不完全一致,直接用==比较两个索引不匹配的Series就会触发这个错误。

优化解决方案

下面提供两种可靠的实现方式,帮你准确识别每个周期内的A(峰值相关节点)和B(Diff2相关节点):

方法1:手动处理局部极值,匹配索引

针对你原来的思路,我们先找出每个周期内符合条件的索引,再给对应位置标记A/B,从根源避免索引不匹配问题:

import pandas as pd
import numpy as np

def mark_poi(group):
    # 初始化POI列为默认值'-'
    poi = pd.Series('-', index=group.index)
    
    # 标记A点:Value的局部最大值(前后10个点均小于当前值)
    mask_a = (group['Value'].shift(10) < group['Value']) & (group['Value'].shift(-10) < group['Value'])
    poi[mask_a] = 'A'
    
    # 标记B点:Diff2的局部最小值(如果需要全局最小,直接取idxmin即可)
    # 这里示例用局部最小逻辑,你可根据需求替换
    mask_b = (group['Diff2'].shift(5) > group['Diff2']) & (group['Diff2'].shift(-5) > group['Diff2'])
    poi[mask_b] = 'B'
    
    # 如果每个周期只保留一个B点,可选择第一个匹配项
    # if mask_b.any():
    #     poi[mask_b.idxmax()] = 'B'
    
    return poi

# 应用到每个周期
Data3['POI'] = Data3.groupby('Cycle#').apply(mark_poi).explode().set_axis(Data3.index, axis=0)

方法2:用scipy的专业极值检测工具

如果需要更精准的局部极值识别,推荐使用scipy.signal.argrelextrema,它能灵活定义“局部”的范围,适配不同数据的噪声情况:

import pandas as pd
import numpy as np
from scipy.signal import argrelextrema

def mark_poi_with_scipy(group):
    poi = pd.Series('-', index=group.index)
    
    # 标记A点:Value的局部最大值,order=10表示前后10个点作为检测窗口
    local_max_indices = group.iloc[argrelextrema(group['Value'].values, np.greater, order=10)[0]].index
    poi.loc[local_max_indices] = 'A'
    
    # 标记B点:Diff2的局部最小值,可调整order参数适配数据
    local_min_indices = group.iloc[argrelextrema(group['Diff2'].values, np.less, order=5)[0]].index
    # 每个周期只保留一个B点,示例取第一个局部最小值
    if not local_min_indices.empty:
        poi.loc[local_min_indices[0]] = 'B'
    
    return poi

Data3['POI'] = Data3.groupby('Cycle#').apply(mark_poi_with_scipy).explode().set_axis(Data3.index, axis=0)

额外建议

  1. 先明确节点定义:你提到最初用全局最值标记不符合预期,大概率是因为A/B点的实际定义和全局最值不匹配。建议可视化几个周期的Value和Diff2曲线,确认:
    • A点是峰值出现的位置?还是上升段的起始点?
    • B点是Diff2的局部最小值?还是下降段的结束点?
  2. 调整窗口参数:无论是shift的步数还是argrelextrema的order参数,都需要根据你的数据周期长度、噪声情况调整,避免误识别噪声带来的伪极值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 15:14:10