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

使用SciPy的find_peaks绘制峰值及检测全局异常值的相关问题

问题1:阈值线不显示的解决

你当前的value列数值量级在1万~22万区间,而你设置的阈值thresh=0.95,对应的阈值线在y轴0.95的位置,远低于数据的显示范围,自然无法看到。
正确的做法是基于你自身的数据分布设置阈值,比如要筛选前5%的高值作为峰值阈值、后5%的低值作为谷值阈值,可以用分位数计算:

# 峰值阈值:取所有value的95分位数,即只有高于该值的峰值才会被识别
peak_thresh = np.quantile(x, 0.95)
# 谷值阈值:取所有value的5分位数,即只有低于该值的谷值才会被识别
valley_thresh = np.quantile(x, 0.05)

之后绘制阈值线的时候用这两个值,就能正常在图中显示了。

问题2:find_peaks参数配置方法

find_peaks的核心参数可以按你的需求(全局异常波动、剧烈变化的峰谷)这么设置:

  • height:峰的最小高度,直接用上面计算的分位数阈值即可,保证只识别超出正常范围的异常值
  • distance:两个峰之间的最小间隔点数,你总共有31条数据,设置为3~10都可以,避免把连续的小幅波动识别为多个峰
  • prominence:峰的突出度,即峰高和两侧基线的差值,设置为10000~30000可以过滤掉小幅波动,只保留剧烈变化的峰谷

修改后可直接运行的完整代码

from scipy.signal import find_peaks
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

df = pd.DataFrame(data={'date':['2020-10-16','2020-10-17','2020-10-18','2020-10-19','2020-10-20','2020-10-21','2020-10-22','2020-10-23','2020-10-24','2020-10-25','2020-10-26','2020-10-27','2020-10-28','2020-10-29','2020-10-30','2020-10-31','2020-11-01','2020-11-02','2020-11-03','2020-11-04','2020-11-05','2020-11-06','2020-11-07','2020-11-08','2020-11-09','2020-11-10','2020-11-11','2020-11-12','2020-11-13','2020-11-14','2020-11-15'],
                        'value':[161967, 161270, 148508, 152442, 157504, 157118, 155674, 134522, 213384, 163242, 217415, 221502, 146267, 143621, 145875, 139488, 104466, 94825, 143686, 151952, 161074, 161417, 135042, 148768, 131428, 127816, 151905, 180498, 177899, 193950, 12]})

# Input signal
t = df.date
x = df.value

# 基于数据分布计算阈值
peak_thresh = np.quantile(x, 0.95)
valley_thresh = np.quantile(x, 0.05)

# Find indices of peaks,prominence设置为20000保证只识别大幅波动的峰
peak_idx, _ = find_peaks(x, height=peak_thresh, distance=5, prominence=20000)
# Find indices of valleys
valley_idx, _ = find_peaks(-x, height=-valley_thresh, distance=5, prominence=20000 )

# Plot signal
plt.figure(figsize=(14,12))
plt.plot(t, x   , color='b', label='data')
plt.scatter(t, x, s=10,c='b',label='value')

# Plot threshold
plt.plot([min(t), max(t)], [peak_thresh, peak_thresh],   '--',  color='r', label='peaks-threshold')
plt.plot([min(t), max(t)], [valley_thresh, valley_thresh], '--',  color='g', label='valleys-threshold')

# Plot peaks (red) and valleys (blue)
plt.plot(t[peak_idx], x[peak_idx],     "x", color='r', s=100, label='peaks')
plt.plot(t[valley_idx], x[valley_idx], "x", color='g', s=100, label='valleys')

plt.xticks(rotation=45)
plt.ylabel('value')
plt.xlabel('timestamp')
plt.title(f'data over time for username=target')
plt.legend( loc='upper left')
plt.gcf().autofmt_xdate()
plt.show()

运行后可以正常识别到3个峰值、1个谷值,阈值线也会正常显示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 09:54:05