Pandas:在每个id的一列中首次出现值后删除行

时间:2017-09-06 11:09:21

标签: python pandas

我使用的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无关。

1 个答案:

答案 0 :(得分:4)

您可以将boolean indexinggroupby创建的mask一起使用自定义功能。

对于每个组,首先要比较shift值,因为需要先包含2。然后按2eq进行比较。但是,还需要匹配每个组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