我有一个数据框,其列如下所示(具有 1400 个唯一的 contextID
和 28 个不同的 IndicatorID
):
ContextID IndicatorID threshold_values AlarmLevel actual_values
7289972 204511 -6.10904 -1 0
7289972 204511 -12.1848 -2 0
7289972 204511 -18.2606 -3 0
7289972 204511 18.19404 1 0
7289972 204511 24.2698 2 0
7289972 204511 30.34557 3 0
7289972 204512 89.94568 1 64.114
7289972 204512 104.2932 2 64.114
7289972 204512 118.6407 3 64.114
7289972 204512 32.55574 -1 64.114
7289972 204512 18.20825 -2 64.114
7289972 204512 3.860765 -3 64.114
7289998 204511 -6.10904 -1 1
7289998 204511 -12.1848 -2 1
7289998 204511 -18.2606 -3 1
7289998 204511 18.19404 1 1
7289998 204511 24.2698 2 1
7289998 204511 30.34557 3 1
7289998 204512 89.94568 1 64.111
7289998 204512 104.2932 2 64.111
7289998 204512 118.6407 3 64.111
7289998 204512 32.55574 -1 64.111
7289998 204512 18.20825 -2 64.111
7289998 204512 3.860765 -3 64.111
actual_values
列是机器传感器读取的实际值。 threshold_values
列包含为各种指标(在 IndicatorID
列中)定义的各种阈值,具体取决于值超过特定限制时将引发的警报。
示例:如果 actual_values
中的值位于为警报级别 -1 和 +1 定义的 threshold_values
之间,则产品没有缺陷。但是,如果该值介于 -1 和 -2 之间,则必须发出 -1 警报(因为它已超过为 -1 定义的阈值),如果该值介于 +1 和 +2 之间,则必须发出警报必须提高+1,依此类推。最后,必须将最大警报级别分配给 ContextID
,这意味着,如果一个指标发出 +1 的警报,而第二个指标发出 -2 的警报,则必须将 -2 的警报级别视为更大,并且指定为该 ContextID
的最终警报(最好在新列中)。
我需要一些帮助来实现这个概念。我想知道是否可以编写这样的实现。
我试图使用 2 个不同的 for
循环来实现它,一个用于所有 ContextID
,另一个用于 IndicatorID
,但不知何故,我无法想出可以实现此任务的逻辑。
我将非常感谢您的帮助和指导。
谢谢
编辑1:
示例:
ContextID IndicatorID threshold_values AlarmLevel actual_values thresh_high alarm_high insideThresh
7291899 204515 0.708226 -3 0.949486 0.742542 -2 FALSE
7291899 204515 0.742542 -2 0.949486 0.76 -1 FALSE
7291899 204515 0.76 -1 0.949486 0.914122 1 FALSE
7291899 204515 0.914122 1 0.949486 0.948438 2 FALSE
7291899 204515 0.948438 2 0.949486 0.982754 3 TRUE
7291899 204515 0.982754 3 0.949486 610.9839 -3 FALSE
thresh_value
的 610.9839
属于不同的 IndicatorID
(204516),但该值用于计算 IndicatorID
(204515) 的警报级别
最佳答案
当然有办法做到这一点。可能比下面的方法更好,但这会起作用。
初始化数据:
import pandas as pd
import numpy as np
thresh = [-6.10904,
-12.1848,
-18.2606,
18.19404,
24.2698,
30.34557,
89.94568,
104.2932,
118.6407,
32.55574,
18.20825,
3.860765]
df = pd.DataFrame({'ContextID':[1]*12+[2]*12,
'IndicatorID':[5]*6+[6]*6+[7]*6+[8]*6,
'threshold_values':thresh*2,
'AlarmLevel':[-1, -2, -3, 1, 2, 3, 3, 2, 1, -1, -2, -3]*2,
'actual_values':[-17]*6+[64.114]*6+[26]*6+[64.111]*6})
我简化了ContextID和IndicatorID,我还为actual_values添加了一些假值,因为你们的值都在正确的范围内。我们想看看当它们超出适当范围时会发生什么。
df = df.sort_values(['ContextID', 'IndicatorID', 'AlarmLevel'])
df['thresh_high'] = df.groupby(['ContextID', 'IndicatorID'])['threshold_values'].shift(-1)
df['alarm_high'] = df.groupby(['ContextID', 'IndicatorID'])['AlarmLevel'].shift(-1)
df['thresh_high'] = df.thresh_high.fillna(np.Inf)
df['alarm_high'] = df.alarm_high.fillna(4)
df['insideThresh'] = (df.actual_values < df.thresh_high) & (df.actual_values > df.threshold_values)
我们对数据帧进行排序,然后创建 thresh_high
和 alarm_high
,它们是 threshold_values
和 AlarmLevel
的移位版本
然后我们创建一个列,仅显示实际值是否落在阈值之间。
alarms = df.loc[df.insideThresh == True] \
.groupby(['ContextID', 'IndicatorID', 'insideThresh'])['AlarmLevel'] \
.apply(lambda x: x.min()+1 if x.min() < 0 else x.min()
)
最后,我们仅针对 actual_values
位于阈值的时间过滤数据帧,然后按 ContextId、IndicatorID 和 insideThresh 进行分组(实际上并不需要最后一个)。
我们获取警报级别并应用一个自定义函数,告诉它如果超出警报级别的最小值为负,则将级别提高 1,否则采用最小值。
关于python-3.x - 如何检查某个值位于哪个阈值水平之间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55033762/