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

Pandas中基于分组极值筛选行:峰值保留逻辑在大数据集下存在残留重复峰值的问题求助

Pandas中基于分组极值筛选行:峰值保留逻辑在大数据集下存在残留重复峰值的问题求助

你好!看起来你正在处理价格/图表数据的峰值筛选需求——要把连续标记为HH(高点)的行里只保留High值最大的那一行,连续标记为LL(低点)的行里只保留Low值最小的那一行。你的循环迭代方法在小数据集上能得到预期结果,但放到大数据集里偶尔会出现残留的重复峰值,我来帮你分析问题并给出更稳健的解决方案。

你的现有情况回顾

先再明确下你的数据和预期:
你构造的示例DataFrame如下:

import pandas as pd

mydict = [
    {'HH': True, 'LL': False, 'High': 10, 'Low': 1},
    {'HH': False, 'LL': True, 'High': 100, 'Low': 20},
    {'HH': True, 'LL': False, 'High': 32, 'Low': 1},
    {'HH': True, 'LL': False, 'High': 30, 'Low': 1},
    {'HH': True, 'LL': False, 'High': 31, 'Low': 1},
    {'HH': False, 'LL': True, 'High': 100, 'Low': 40},
    {'HH': False, 'LL': True, 'High': 100, 'Low': 45},
    {'HH': False, 'LL': True, 'High': 100, 'Low': 42},
    {'HH': False, 'LL': True, 'High': 100, 'Low': 44},
    {'HH': True, 'LL': False, 'High': 50, 'Low': 1},
]

df = pd.DataFrame(mydict)

你期望的结果是每个连续的HH组只保留最高High的行,每个连续的LL组只保留最低Low的行,得到的结果如下:

HH     LL  High  Low
0   True  False    10    1
1  False   True   100   20
2   True  False    32    1
3  False  False    30    1
4  False  False    31    1
5  False   True   100   40
6  False  False   100   45
7  False  False   100   42
8  False  False   100   44
9   True  False    50    1

现有方法的问题分析

你的循环迭代逻辑是通过逐次标记那些比前后同类型峰值更低(HH)或更高(LL)的行,然后将它们的HH/LL设为False,直到没有需要处理的行为止。这种方法在小数据集上能工作,但在大数据集容易出问题的原因有两个:

  1. 迭代逻辑的局限性:依赖相邻行的比较,当连续峰值组内有多个非极值行时,可能需要多次循环才能清除,但如果某次循环后临时的df3为空,循环会提前终止,导致残留的非极值峰值;
  2. 效率低下:大数据集下循环次数多,不仅性能差,还容易出现边界条件处理不当的情况。

更稳健的解决方案:分组找极值

核心思路是先对连续的HH/LL区块进行分组,然后在每个分组内直接定位极值对应的行,只保留该行的HH/LL标记,一次处理所有区块,避免迭代遗漏。

具体代码实现

# 复制原DataFrame,避免修改原始数据
df_clean = df.copy()

# ---------------------- 处理HH峰值 ----------------------
# 生成连续HH的分组标识:当HH状态变化时,分组编号+1
hh_groups = (df_clean['HH'] != df_clean['HH'].shift()).cumsum()
# 仅筛选出HH为True的有效分组
hh_valid_groups = hh_groups[df_clean['HH']]

# 对每个HH分组,找到High值最大的行索引
hh_peak_indices = df_clean.groupby(hh_valid_groups)['High'].idxmax()

# 先把所有HH设为False,再只保留峰值行的HH为True
df_clean['HH'] = False
df_clean.loc[hh_peak_indices, 'HH'] = True

# ---------------------- 处理LL谷值 ----------------------
# 生成连续LL的分组标识:当LL状态变化时,分组编号+1
ll_groups = (df_clean['LL'] != df_clean['LL'].shift()).cumsum()
# 仅筛选出LL为True的有效分组
ll_valid_groups = ll_groups[df_clean['LL']]

# 对每个LL分组,找到Low值最小的行索引
ll_peak_indices = df_clean.groupby(ll_valid_groups)['Low'].idxmin()

# 先把所有LL设为False,再只保留谷值行的LL为True
df_clean['LL'] = False
df_clean.loc[ll_peak_indices, 'LL'] = True

# 查看处理后的结果
print(df_clean)

代码逻辑说明

  1. 分组标识生成:通过比较当前行和上一行的HH/LL状态,生成连续区块的分组编号,确保每个连续的HH/LL区块被归为同一组;
  2. 极值定位:使用groupby结合idxmax/idxmin直接找到每个分组内的极值行索引,这一步是一次性完成所有分组的处理;
  3. 标记重置与保留:先将所有HH/LL设为False,再把极值行的标记恢复为True,确保每组只保留一个有效峰值。

方案优势

  • 无遗漏:一次性处理所有连续峰值区块,不会出现迭代方法的残留问题;
  • 高效:避免循环迭代,大数据集下性能提升明显;
  • 逻辑清晰:直接针对分组找极值,符合你的业务需求逻辑,便于维护和扩展。

备注:内容来源于stack exchange,提问作者Viktor

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.20 11:14:50