python - 不均匀时间序列中的峰值检测
问题描述
我正在使用一个包含措施的数据集,并结合了以下内容datetime
:
datetime value
2017-01-01 00:01:00,32.7
2017-01-01 00:03:00,37.8
2017-01-01 00:04:05,35.0
2017-01-01 00:05:37,101.1
2017-01-01 00:07:00,39.1
2017-01-01 00:09:00,38.9
我正在尝试检测并删除可能出现的潜在峰值,例如2017-01-01 00:05:37,101.1
测量值。
到目前为止我发现的一些东西:
- 这个数据集的时间间隔从 15 秒到 25 分钟不等,非常不均匀;
- 峰的宽度无法事先确定
- 峰高明显且显着偏离其他值
时间步的归一化只应在去除异常值后进行,因为它们会干扰结果
由于其他异常(例如,负值,平线),即使没有它们,它也会由于峰值而产生错误的值,这是“不可能的”;
find_peaks
期待均匀间隔的时间序列,因此之前的解决方案不适用于我们拥有的不规则时间序列;- 在那个问题上,我忘了提到时间序列不均匀的关键点。
我到处搜索,但什么也找不到。实现将在 Python 中,但我愿意挖掘其他语言以获取逻辑。
解决方案
我已在github上将此代码发布给将来遇到此问题或类似问题的任何人。
经过大量的试验和错误,我认为我创造了一些有效的东西。使用@user58697 告诉我的内容,我设法创建了一个代码来检测阈值之间的每个峰值。
通过使用他/她解释的逻辑,if ((flow[i+1] - flow[i]) / (time[i+1] - time[i]) > threshold
我编写了以下代码:
首先读取.csv
并解析日期,然后拆分为两个 numpy 数组:
dataset = pd.read_csv('https://raw.githubusercontent.com/MigasTigas/peak_removal/master/dataset_simple_example.csv', parse_dates=['date'])
dataset = dataset.sort_values(by=['date']).reset_index(drop=True).to_numpy() # Sort and convert to numpy array
# Split into 2 arrays
values = [float(i[1]) for i in dataset] # Flow values, in float
values = np.array(values)
dates = [i[0].to_pydatetime() for i in dataset]
dates = np.array(dates)
然后将 应用于(flow[i+1] - flow[i]) / (time[i+1] - time[i])
整个数据集:
flow = np.diff(values)
time = np.diff(dates).tolist()
time = np.divide(time, np.power(10, 9))
slopes = np.divide(flow, time) # (flow[i+1] - flow[i]) / (time[i+1] - time[i])
slopes = np.insert(slopes, 0, 0, axis=0) # Since we "lose" the first index, this one is 0, just for alignments
x
最后,为了检测峰值,我们将数据减少到每个数秒的滚动窗口。这样我们就可以很容易地检测到它们:
# ROLLING WINDOW
size = len(dataset)
rolling_window = []
rolling_window_indexes = []
RW = []
RWi = []
window_size = 240 # Seconds
dates = [i.to_pydatetime() for i in dataset['date']]
dates = np.array(dates)
# create the rollings windows
for line in range(size):
limit_stamp = dates[line] + datetime.timedelta(seconds=window_size)
for subline in range(line, size, 1):
if dates[subline] <= limit_stamp:
rolling_window.append(slopes[subline]) # Values of the slopes
rolling_window_indexes.append(subline) # Indexes of the respective values
else:
RW.append(rolling_window)
if line != size: # To prevent clearing the last rolling window
rolling_window = []
RWi.append(rolling_window_indexes)
if line != size:
rolling_window_indexes = []
break
else:
# To get the last rolling window since it breaks before append
RW.append(rolling_window)
RWi.append(rolling_window_indexes)
获得所有滚动窗口后,我们开始有趣:
t = 0.3 # Threshold
peaks = []
for index, rollWin in enumerate(RW):
if rollWin[0] > t: # If the first value is greater of threshold
top = rollWin[0] # Sets as a possible peak
bottom = np.min(rollWin) # Finds the minimum of the peak
if bottom < -t: # If less than the negative threshold
bottomIndex = int(np.argmin(rollWin)) # Find it's index
for peak in range(0, bottomIndex, 1): # Appends all points between the first index of the rolling window until the bottomIndex
peaks.append(RWi[index][peak])
这段代码背后的想法是每个峰值都有一个上升和下降,如果两者都大于规定的阈值,那么它是一个异常峰值以及它们之间的所有峰值:
翻译成使用的真实数据集的地方,发布在github 上:
推荐阅读
- python-3.x - 使用 pandas 处理 Excel 文件时出现错误消息“Traceback(最近一次调用最后一次)”
- tensorflow - 无法使用 tf.decode_csv() 正确读取一个数组 csv 文件
- javascript - 模块没有导出成员,“请求”
- javascript - Moment .JS - 为什么差异不是全年格式
- javascript - 如何在 Javascript 中使用 ASP 变量?
- ios - 后台任务在持有 WebKit ProcessAssertion 时过期
- c# - 如何在其外部的 WPF 表单内调用函数
- maven - rtMavenDeployer 怎么添加属性?
- javascript - AWS s3 重定向到另一个 s3 存储桶
- c++ - 我可以在其析构函数中使用指向被破坏对象的指针吗?