Python离散数据极值查找:如何在pandas离散数据中定位A/B/C/D特征点
离散序列A、B、C、D四点定位方法


点定义说明
四个点的先后顺序为:序列起始位置 → A → C → B → D,满足如下规则:
- A是序列起始到C之间的最大值点
- C是A到B之间的最小值点
- B是C到D之间的最大值点
- D是B之后的第一个显著低点
验证测试数据
给定测试序列:[1, 2, 3, 10, 13, 15, 20, 50, 49, 49, 32, 33, 35, 36, 35, 34, 33, 34, 35, 36, 30, 27, 22, 15, 15, 17, 20, 27, 30, 32, 50, 56, 67, 85, 100, 99, 94, 83, 72, 59, 66, 67, 89, 90, 92, 127, 130, 189]
预期输出结果:
- A = 50
- B = 100
- C = 15
- D = 59
实现方案
由于四点定义存在循环依赖,我们通过按先后顺序找极值的方式打破循环,逻辑如下:
- 先找序列第一个显著峰值,即为A
- 在A之后的子序列中找最小值点,即为C
- 在C之后的子序列中找第一个显著峰值,即为B
- 在B之后的子序列中找第一个显著低点,即为D
代码实现(Python+Pandas)
需要依赖scipy库的find_peaks方法识别峰值,谷值通过识别负序列的峰值实现:
import pandas as pd import numpy as np from scipy.signal import find_peaks # 加载测试数据 data = [1, 2, 3, 10, 13, 15, 20, 50, 49, 49, 32, 33, 35, 36, 35, 34, 33, 34, 35, 36, 30, 27, 22, 15, 15, 17, 20, 27, 30, 32, 50, 56, 67, 85, 100, 99, 94, 83, 72, 59, 66, 67, 89, 90, 92, 127, 130, 189] s = pd.Series(data) # 1. 找第一个显著峰值A,调整distance参数过滤小波动峰值 peaks, _ = find_peaks(s, distance=10) A_val = s.iloc[peaks[0]] A_idx = peaks[0] # 2. 找A之后的最小值C sub_after_A = s.iloc[A_idx+1:] C_idx = sub_after_A.idxmin() C_val = s.iloc[C_idx] # 3. 找C之后的第一个显著峰值B sub_after_C = s.iloc[C_idx+1:] peaks_after_C, _ = find_peaks(sub_after_C, distance=10) # 转换为原序列索引 B_idx = sub_after_C.index[peaks_after_C[0]] B_val = s.iloc[B_idx] # 4. 找B之后的第一个显著低点D sub_after_B = s.iloc[B_idx+1:] # 找谷值:对负序列找峰值 valleys_after_B, _ = find_peaks(-sub_after_B, distance=5) D_idx = sub_after_B.index[valleys_after_B[0]] D_val = s.iloc[D_idx] # 输出结果 print(f"A = {A_val}") print(f"B = {B_val}") print(f"C = {C_val}") print(f"D = {D_val}")
输出结果
运行上述代码后输出和预期完全一致:
A = 50 B = 100 C = 15 D = 59
参数调整说明
如果你的序列波动更大,可以调整find_peaks的如下参数适配:
distance:两个峰值之间的最小间隔点数,过滤小波动prominence:峰值的突出程度,避免把局部小凸起识别为峰值height:峰值的最低高度阈值
内容的提问来源于stack exchange,提问作者NNNNNNN
相关产品推荐
相关产品推荐

