我有一个数据框,其列如下所示(具有1400个唯一的contextID
和28个不同的IndicatorID
s):
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
的{{1}}属于不同的610.9839
(204516),但是此值用于计算IndicatorID
的警报级别(204515)>
答案 0 :(得分:2)
当然有办法做到这一点。可能比下面的方法更好,但这是可行的。
初始化数据:
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,我还为real_value放入了一些假值,因为你们都在适当的范围内。我们想看看当它们超出适当范围时会发生什么。
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,否则为最小值。