python - 在图形和表格中识别时间序列何时通过阈值
问题描述
我有一个时间序列,将“实际”与“预测”通道值进行比较。(这是针对机器的预测性维护应用)
由于我在机器全新时训练模型,因此我对这些渠道之间的比较超过特定阈值的时间感兴趣。
理想情况下,我希望能够在图表和表格中识别这些事件。
下面是一些示例数据行以及我试图对图表执行的操作。
非常感谢您的帮助!
数据格式:
Index Time Actual Predicted Score
1 6/10/2020 0:00 134 124 8.1%
2 6/10/2020 1:00 135 127 6.3%
3 6/10/2020 2:00 129 125 3.2%
4 6/10/2020 3:00 134 130 3.1%
5 6/10/2020 4:00 131 127 3.1%
6 6/10/2020 5:00 134 127 5.5%
7 6/10/2020 6:00 129 125 3.2%
8 6/10/2020 7:00 130 133 -2.3%
9 6/10/2020 8:00 133 138 -3.6%
10 6/10/2020 9:00 125 129 -3.1%
11 6/10/2020 10:00 125 131 -4.6%
12 6/10/2020 11:00 126 136 -7.4%
13 6/10/2020 12:00 128 136 -5.9%
14 6/10/2020 13:00 133 138 -3.6%
15 6/10/2020 14:00 134 130 3.1%
16 6/10/2020 15:00 129 125 3.2%
17 6/10/2020 16:00 129 125 3.2%
因此,在这种特殊情况下,我希望有一个表格,我可以在其中检测到它低于特定阈值并回升到它之上的时间。例如-4.0。
ID EventType EventTime
11 Red 6/10/2020 10:00
14 Green 6/10/2020 13:00
然后,理想情况下,我还希望能够在图表上突出显示此类事件。
解决方案
变化的计算略有不同。基本步骤是:
- 将分数转换为
float
(删除百分比) - 标记低于 -4 截止值的所有分数(使用 1,否则为 0)。
- 对
diff()
重新标记的分数进行评分 diff()
根据您要分配的颜色替换这些值。
我将这些步骤分成不同的列,但如果您不想将垃圾添加到您的df
:
df['Score'] = df['Score'].str.replace('%','').astype(float)
df['Below_Cutoff'] = np.where(df['Score'] <= -4, 1, 0)
df["Changes"] = df['Below_Cutoff'].diff()
df['Change_Colors'] = df['Changes'].map({1:'Red', -1:'Green', 0:np.nan})
结果:
Time Actual Predicted ... Below_Cutoff Changes Change_Colors
1 2020-06-10 00:00:00 134 124 ... 0 NaN NaN
2 2020-06-10 01:00:00 135 127 ... 0 0.0 NaN
3 2020-06-10 02:00:00 129 125 ... 0 0.0 NaN
4 2020-06-10 03:00:00 134 130 ... 0 0.0 NaN
5 2020-06-10 04:00:00 131 127 ... 0 0.0 NaN
6 2020-06-10 05:00:00 134 127 ... 0 0.0 NaN
7 2020-06-10 06:00:00 129 125 ... 0 0.0 NaN
8 2020-06-10 07:00:00 130 133 ... 0 0.0 NaN
9 2020-06-10 08:00:00 133 138 ... 0 0.0 NaN
10 2020-06-10 09:00:00 125 129 ... 0 0.0 NaN
11 2020-06-10 10:00:00 125 131 ... 1 1.0 Red
12 2020-06-10 11:00:00 126 136 ... 1 0.0 NaN
13 2020-06-10 12:00:00 128 136 ... 1 0.0 NaN
14 2020-06-10 13:00:00 133 138 ... 0 -1.0 Green
15 2020-06-10 14:00:00 134 130 ... 0 0.0 NaN
16 2020-06-10 15:00:00 129 125 ... 0 0.0 NaN
17 2020-06-10 16:00:00 129 125 ... 0 0.0 NaN
请注意,在上面,第一个条目diff()
始终是 NaN;如果您只想检测阈值交叉,我认为这不是问题。但是如果第一个值低于 -4 并且您希望那里有一个红点,那么这将失败。
所以要得到一个只有截止的表,你可以这样做:
only_changes = df[~pd.isna(df['Change_Colors'])]
要进行绘图,您可以执行以下操作(这类似于 Andrea 的答案,但特定于我的示例):
fig, ax = plt.subplots(figsize=(7,3.5))
ax.plot(df['Time'], df['Score'])
ax.scatter(only_changes['Time'], only_changes['Score'], c=only_changes['Change_Colors'])
ax.xaxis.set_major_locator(mdates.HourLocator([0,4,8,12,16,20,24]))
ax.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))
ax.hlines(-4, min(df['Time']), max(df['Time']), colors = 'r')
标记实际的交叉口
此外,如果您想插值以估计实际阈值交叉的标签,您可以创建更高频率的时间戳来插值:
minutes = pd.date_range(df['Time'].min(), df['Time'].max(), freq='1T')
interp = pd.Series(np.interp(minutes, df['Time'], df['Score']))
interp.index = minutes
only_changes = pd.Series(np.where(interp <= -4, 1, 0)).diff().map({1:'Red', -1:'Green', 0:np.nan})
only_changes = only_changes[~pd.isna(only_changes)]
然后将scatter
上面相同绘图代码的调用替换为:
ax.scatter(interp.index[only_changes.index], interp[only_changes.index], c=only_changes)
但请注意,现在红/绿点并未放置在数据中的实际测量点上!
推荐阅读
- laravel - 实时服务器上的 dompdf laravel,无法下载 pdf 并返回错误 500
- python - 如何编写一个将在数小时内运行的 while 循环
- android - Android 辅助功能服务 - GestureDescription.Builder - 未正确分派复杂手势滑动
- php - wordpress 自定义帖子类型 register_post_type 删除单个视图但保留存档页面
- c++ - 将多维数组作为 void * 传递给外部“C”函数
- python - Django Rest Framework 没有从我的数据库中检索数据
- sql - 规范化 - 清除 sql 列中重复的拼写错误值的最佳方法
- recaptcha - 获取请求的 Recaptcha v3 保护
- wordpress - 将自定义分类法添加到所有帖子页面
- amazon-cloudformation - 创建cloudformation资源倍增