如何将逻辑应用于数据帧中的行子集?

时间:2019-05-06 14:51:30

标签: python pandas

在此问题中,我试图了解何时应基于“值”生成警报。

如果先前的5个值大于10,则创建警报。警报将继续保持活动状态,直到该值降至7.5以下。现在,一旦警报不再处于活动状态,并且到达前5个值都超过10的阶段,便会再次创建警报。

这是我用来执行此操作的逻辑:

NUM_PREV_ROWS = 5
PREV_5_THRESHOLD = 10.0
PREV_THRESHOLD = 7.5

d = {'device': ['a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
                    'a','a','a','a','a','b','b','b','b','b',
                    'b','b','b','b','b','b','b','b','b','b','b','b','b','b','b','b','b'] , 
     'value': [11,11,11,11,11,11,11,8,9,11,11,11,11,11,8,9,6,11,11,11,11,11,11,11,11,11,11,11,11,8,9,11,11,11,11,11,8,9,6,11,11,11,11,11]}
df = pd.DataFrame(data=d)

df['prev>10'] = df['value']>PREV_5_THRESHOLD
df['prev5>10'] = df['prev>10'].rolling(NUM_PREV_ROWS).sum()
df['prev>7.5'] = df['value']>PREV_THRESHOLD 

alert = False
alert_series = []
for row in df.iterrows():
    if row[1]['prev5>10']==NUM_PREV_ROWS:
        alert = True
    if row[1]['prev>7.5']==False:
        alert = False
    alert_series.append(alert)

df['alert'] = alert_series

问题是,遇到新设备时,循环应重新启动(在这种情况下,应首先为A运行,然后在遇到该设备时在B之上运行)。我该怎么办?

这是具有当前逻辑的输出:

print(df)

    value  prev>10  prev5>10  prev>7.5  alert
a      11     True       NaN      True  False
a      11     True       NaN      True  False
a      11     True       NaN      True  False
a      11     True       NaN      True  False
a      11     True       5.0      True   True
a      11     True       5.0      True   True
a      11     True       5.0      True   True
a       8    False       4.0      True   True
a       9    False       3.0      True   True
a      11     True       3.0      True   True
a     11     True       3.0      True   True
a     11     True       3.0      True   True
a     11     True       4.0      True   True
a     11     True       5.0      True   True
a      8    False       4.0      True   True
a      9    False       3.0      True   True
a      6    False       2.0     False  False
a     11     True       2.0      True  False
a     11     True       2.0      True  False
a     11     True       3.0      True  False
a     11     True       4.0      True  False
a     11     True       5.0      True   True
b      11     True      5.0      True  True
b      11     True      5.0     True  True
b      11     True      5.0      True  True
b      11     True      5.0      True  True
b      11     True       5.0      True   True
b      11     True       5.0      True   True
b      11     True       5.0      True   True
b       8    False       4.0      True   True
b       9    False       3.0      True   True
b      11     True       3.0      True   True
b     11     True       3.0      True   True
b     11     True       3.0      True   True
b     11     True       4.0      True   True
b     11     True       5.0      True   True
b      8    False       4.0      True   True
b      9    False       3.0      True   True
b      6    False       2.0     False  False
b     11     True       2.0      True  False
b     11     True       2.0      True  False
b     11     True       3.0      True  False
b     11     True       4.0      True  False
b     11     True       5.0      True   True

感谢所有帮助!

2 个答案:

答案 0 :(得分:0)

我不确定这是否是最好的方法,但是使用groupby重置循环又如何呢?

def f(df):

    alert = False
    alert_series = []
    for row in df.iterrows():
        if row[1]['prev5>10']==NUM_PREV_ROWS:
            alert = True
        if row[1]['prev>7.5']==False:
            alert = False
        alert_series.append(alert)

    return pd.DataFrame({'alert': alert_series})

df['alert'] = df.groupby("device").apply(f).reset_index(drop=True)

答案 1 :(得分:0)

首先,您需要一个对块进行解析的方法。我尝试了另一种矢量化方法:

def larger_than_threshold(
    data,
    previous_5_threshold=PREV_5_THRESHOLD,
    amount=NUM_PREV_ROWS,
    previous_threshold=PREV_THRESHOLD,
):
    prev5_over_limit = (
        ((data > previous_5_threshold).rolling(amount).sum() == amount)
        .astype(int)
        .diff()
        == 1
    ).replace({False: None})
    prev_under_threshold = (data < previous_threshold)

    prev5_over_limit[prev_under_threshold] = False

    return prev5_over_limit.fillna(method="ffill").fillna(False)

这将接受您的value系列数据

您也可以在这里使用迭代方法。

然后,您可以使用groupby.transform将其应用于每个单独的设备

df["alert"] = df.groupby("device").transform(larger_than_threshold)
相关问题