我使用的Dataframe看起来像这样:
ID Alarm
1 1
1 2
1 3
2 3
2 1
2 2
2 4
3 4
3 2
我想在第一次出现Alarm = 2后分别删除每个ID的所有行。所以输出应该是:
ID Alarm
1 1
1 2
2 3
2 1
2 2
3 4
3 2
最简单的方法是什么?这个案例的pandas方法是否存在?我尝试使用loc
df.loc[: df[(df['Alarm'] == 2)].index[0], :])
创建一些内容,但它会在第一次发生Alarm = 2后删除所有行,与ID无关。
答案 0 :(得分:4)
您可以将boolean indexing
与groupby
创建的mask
一起使用自定义功能。
对于每个组,首先要比较shift
值,因为需要先包含2
。然后按2
按eq
进行比较。但是,还需要匹配每个组2
下的多个值,因此需要cumsum
并与0
进行比较 - False
行将被删除。
df = df[df.groupby('ID')['Alarm'].apply(lambda x: x.shift().eq(2).cumsum().eq(0))]
print (df)
ID Alarm
0 1 1
1 1 2
3 2 3
4 2 1
5 2 2
7 3 4
8 3 2
为了更好地理解更多数据:
df['a'] = df.groupby('ID')['Alarm'].apply(lambda x: x.shift())
df['b'] = df.groupby('ID')['Alarm'].apply(lambda x: x.shift().eq(2))
df['c'] = df.groupby('ID')['Alarm'].apply(lambda x: x.shift().eq(2).cumsum())
df['d'] = df.groupby('ID')['Alarm'].apply(lambda x: x.shift().eq(2).cumsum().eq(0))
print (df)
ID Alarm a b c d
0 1 1 NaN False 0 True
1 1 2 1.0 False 0 True
2 1 2 2.0 True 1 False
3 1 2 2.0 True 2 False
4 1 3 2.0 True 3 False
5 2 3 NaN False 0 True
6 2 1 3.0 False 0 True
7 2 2 1.0 False 0 True
8 2 4 2.0 True 1 False
9 3 4 NaN False 0 True
10 3 2 4.0 False 0 True