如何检查值位于哪个阈值水平之间?

时间:2019-03-06 23:22:30

标签: python-3.x pandas logic

我有一个数据框,其列如下所示(具有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)

1 个答案:

答案 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_highalarm_high的移位版本的threshold_valuesAlarmLevel

然后,我们创建一列,仅显示实际值是否在阈值之间。

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,否则为最小值。