Python Pandas:如何获取多周期数据中每个周期内的两个压力峰值最大值
循环压力数据双峰值提取方案
问题背景
从运行过数千次循环的设备导入运行数据,每次循环时长为数分钟,包含2个压力峰值需要提取记录,示例循环的压力曲线如下:
该次循环的两个峰值分别为807 psi和936 psi。数据已完成排序,可判定循环的启停状态(已通过group列标记每个循环所属分组)。
原有实现方案为:
df2 = df.groupby('group')['Pressure'].nlargest(2).rename_axis (index=['group', 'row_index'])
该方案仅能返回每个周期数值最大的2个点,部分周期中这2个点属于同一峰值的临近位置,无法识别两个独立的真实峰值。
以下为单个周期的示例数据:
import pandas as pd data = {'Pressure' : [100,112,114,120,123,420,123,1230,1320,1,23,13,13,13,123,13,123,3,222,2303,1233,1233,1,1,30,20,40,401,10,40,12,122,1,12,333]} df = pd.DataFrame(data)
该示例的真实峰值为1320和2303,需要过滤峰值前缓慢上升段的无效数值。
实现方案
核心思路
- 采用峰值检测算法识别独立峰值,避免同峰多点的问题
- 可通过参数过滤低幅度波动和冗余峰值,适配业务场景
- 支持groupby批量处理所有循环,性能满足万级以上周期的数据处理需求
代码实现
依赖安装(如未安装scipy):pip install scipy pandas numpy
完整代码:
import pandas as pd import numpy as np from scipy.signal import find_peaks def extract_two_peaks(pressure_ser, min_peak_height=500, min_peak_gap=10): """ 从单个周期的压力序列中提取最大的两个独立峰值 :param pressure_ser: 单个周期的压力数据Series(已按时间排序) :param min_peak_height: 最低峰值阈值,低于该值的波动直接过滤,可根据实际业务调整 :param min_peak_gap: 两个峰值之间的最小点数间隔,避免同一峰值的临近点被识别为独立峰 :return: 两个峰值,按从大到小排列,不足两个时补空值 """ # 检测符合条件的峰值 peak_indexes, _ = find_peaks(pressure_ser, height=min_peak_height, distance=min_peak_gap) # 提取峰值对应数值 peak_values = pressure_ser.iloc[peak_indexes] # 取最大的两个峰值 top2 = peak_values.nlargest(2).tolist() # 补全空值避免格式异常 while len(top2) < 2: top2.append(np.nan) return pd.Series(top2, index=['peak_1', 'peak_2']) # 单周期测试 test_data = {'Pressure' : [100,112,114,120,123,420,123,1230,1320,1,23,13,13,13,123,13,123,3,222,2303,1233,1233,1,1,30,20,40,401,10,40,12,122,1,12,333]} test_df = pd.DataFrame(test_data) print(extract_two_peaks(test_df['Pressure'])) # 输出: # peak_1 2303 # peak_2 1320 # dtype: int64 # 全量数据批量处理 # 假设全量数据df已包含group列标记所属循环 result = df.groupby('group')['Pressure'].apply(extract_two_peaks).unstack()
参数调整说明
min_peak_height:可根据设备正常运行的峰值下限调整,比如示例中峰值均在1000以上,设置为500即可直接过滤420、333等上升段小值min_peak_gap:可根据单个峰值的持续点数调整,比如单个峰值从上升到回落共占5个数据点,设置为10即可保证不会把同一峰的两个高点识别为两个独立峰值
内容的提问来源于stack exchange,提问作者SeanK22
相关产品推荐
相关产品推荐

