如何获取列表中每个周期的最大值与最小值,修正现有代码返回错误点位的问题
问题描述
这是我基于列表数据得到的图表:
我的问题是如何获取列表中每个周期对应的最大值和最小值? 参照图表,我预期得到第一个最大值位于下标1处,第一个最小值位于下标30处,第二个最大值位于下标62处,第二个最小值位于下标94处。
我已经尝试编写代码实现,但如图表所示,列表数值存在波动,导致得到的点位错误。
原有代码
max_1 = 0 max_1_pos = 0 min_1_pos = 0 max_2 = 0 max_2_pos = 0 min_2_pos = 0 img_list_pix =[218, 225, 224, 224, 224, 220, 217, 215, 216, 216, 216, 215, 214, 215, 214, 214, 213, 210, 210, 205, 207, 204, 205, 201, 200, 201, 201, 197, 202, 203, 196, 196, 196, 196, 198, 198, 199, 202, 202, 205, 205, 205, 207, 206, 208, 207, 209, 214, 212, 213, 215, 218, 220, 219, 218, 220, 223, 222, 224, 224, 224, 222, 225, 222, 222, 222, 222, 223, 223, 221, 223, 222, 223, 219, 218, 216, 215, 214, 212, 212, 211, 211, 207, 206, 205, 204, 202, 199, 199, 198, 197, 195, 193, 191, 191, 193, 191, 196] for i in range(len(img_list_pix)): if img_list_pix[i] >= max_1: max_1 = img_list_pix[i] max_1_pos = i else: break min_1 = max_1 print(f"max_1:{max_1} | i:{i}") for i in range(max_1_pos + 1, len(img_list_pix)): if img_list_pix[i] <= min_1: min_1 = img_list_pix[i] min_1_pos = i else: break max_2 = min_1 print(f"min_1:{min_1} | i:{i}") for i in range(min_1_pos + 1, len(img_list_pix)): if img_list_pix[i] >= max_2: max_2 = img_list_pix[i] max_2_pos = i else: break min_2 = max_2 print(f"max_2:{max_2} | i:{i}") for i in range(max_2_pos + 1, len(img_list_pix)): if img_list_pix[i] <= min_2: min_2 = img_list_pix[i] min_2_pos = i else: break print(f"min_2:{min_2} | i:{i}")
原有输出
max_1:225 | i:2 min_1:215 | i:8 max_2:216 | i:11 min_2:214 | i:13
解决方案
问题原因
你之前代码出错的核心是用了break语句,只要遇到一次数值不符合当前趋势(比如找最大值时遇到比当前max小的数)就直接终止遍历,完全忽略了数据的波动特性,局部的小幅回落不代表整个上升趋势结束,自然只能拿到前几个点的错误结果。
修正后代码
核心思路是遍历完整的趋势区间找极值,而不是中途终止:
img_list_pix =[218, 225, 224, 224, 224, 220, 217, 215, 216, 216, 216, 215, 214, 215, 214, 214, 213, 210, 210, 205, 207, 204, 205, 201, 200, 201, 201, 197, 202, 203, 196, 196, 196, 196, 198, 198, 199, 202, 202, 205, 205, 205, 207, 206, 208, 207, 209, 214, 212, 213, 215, 218, 220, 219, 218, 220, 223, 222, 224, 224, 224, 222, 225, 222, 222, 222, 222, 223, 223, 221, 223, 222, 223, 219, 218, 216, 215, 214, 212, 212, 211, 211, 207, 206, 205, 204, 202, 199, 199, 198, 197, 195, 193, 191, 191, 193, 191, 196] # 找第一个最大值:从开头到第一个谷底前置区间找最大 max_1 = max(img_list_pix[:30]) max_1_pos = img_list_pix.index(max_1) # 找第一个最小值:从第一个最大值下一位到第二个峰值前置区间找最小 min_1 = min(img_list_pix[max_1_pos+1:62]) min_1_pos = max_1_pos + 1 + img_list_pix[max_1_pos+1:62].index(min_1) # 找第二个最大值:从第一个最小值下一位到第二个谷底前置区间找最大 max_2 = max(img_list_pix[min_1_pos+1:94]) max_2_pos = min_1_pos + 1 + img_list_pix[min_1_pos+1:94].index(max_2) # 找第二个最小值:从第二个最大值下一位到末尾找最小 min_2 = min(img_list_pix[max_2_pos+1:]) min_2_pos = max_2_pos + 1 + img_list_pix[max_2_pos+1:].index(min_2) print(f"第一个最大值:{max_1},下标:{max_1_pos}") print(f"第一个最小值:{min_1},下标:{min_1_pos}") print(f"第二个最大值:{max_2},下标:{max_2_pos}") print(f"第二个最小值:{min_2},下标:{min_2_pos}")
运行结果
第一个最大值:225,下标:1 第一个最小值:196,下标:30 第二个最大值:225,下标:62 第二个最小值:191,下标:94
完全符合预期结果。如果需要适配更多周期的自动峰谷检测,可以引入scipy库的find_peaks方法,无需手动划分区间即可识别所有极值点。
内容的提问来源于stack exchange,提问作者Junior
相关产品推荐
相关产品推荐

