python-3.x 如何选择panda中groupby第一次出现某个值的行,以及第一次出现后续值的行

wljmcqd8  于 2023-02-01  发布在  Python
关注(0)|答案(4)|浏览(207)

我有一个 Dataframe ,看起来像这样:

import pandas as pd

df = pd.DataFrame({'id': [1,1,1,1,1,2,2,2,2], 'time': [1,2,3,4,5,4,7,8,9], 'taken': [0,1,1,0,1,0,1,0,1]})

df已经是关于idtime的订单。
我想只保留taken具有1id的值的行,并且如果在列taken中有两个(或更多)结果1,则只保留其中的第一个。
我的输出df应该是这样的:

id  time  taken
1   1     2      1
4   1     5      1
6   2     7      1
8   2     9      1
    • 第二个示例**

为了让问题更清楚一点,如果 Dataframe 如下所示:

df = pd.DataFrame({'id': [1,1,1,1,1,2,2,2,2], 'time': [1,2,3,4,5,4,7,8,9], 'taken': [0,1,1,1,1,1,1,0,1]})

然后输出 Dataframe 应如下所示:

id  time  taken
1   1     2      1
5   2     4      1
8   2     9      1

有什么办法吗?

enxuqcxy

enxuqcxy1#

通过按id分组创建布尔掩码,然后取taken为True但其移位值不为True的值。

df1 = pd.DataFrame({'id': [1,1,1,1,1,2,2,2,2], 'time': [1,2,3,4,5,4,7,8,9], 'taken': [0,1,1,0,1,0,1,0,1]})
df2 = pd.DataFrame({'id': [1,1,1,1,1,2,2,2,2], 'time': [1,2,3,4,5,4,7,8,9], 'taken': [0,1,1,1,1,1,1,0,1]}) 

df = df1  # First example.
>>> df[df.groupby('id')['taken'].shift().ne(True) & df['taken']]
   id  time  taken
1   1     2      1
4   1     5      1
6   2     7      1
8   2     9      1

df = df2  # Second example.
>>> df[df.groupby('id')['taken'].shift().ne(True) & df['taken']]
   id  time  taken
1   1     2      1
5   2     4      1
8   2     9      1
0mkxixxg

0mkxixxg2#

这里有一个方法:

taken_is_one = df.taken.eq(1)
df[taken_is_one & (~taken_is_one.shift(-1, fill_value=False) 
                | df.groupby('id').id.shift(1).isna())]

   id  time  taken
1   1     2      1
5   2     4      1
8   2     9      1

其中:

~taken_is_one.shift(-1, fill_value=False)

0     True
1     True
2    False
3    False
4     True
5    False
6     True
7    False
8     True

只有当taken中的下一个值不是1时,我们才有True,因此通过与&组合,我们可以在两个条件都是True时进行索引。

s6fujrry

s6fujrry3#

您可以使用多个掩码来执行此操作。首先检查取值为1的位置。然后您需要检查以下任一项:仍然是相同的id,并且与前一行的差异不是0或不是相同的想法:

print (df[df.taken.eq(1) & (df.id.diff().eq(0) & df.taken.diff().ne(0) | df.id.diff().ne(0))])
   id  time  taken
1   1     2      1
4   1     5      1
6   2     7      1
8   2     9      1
h5qlskok

h5qlskok4#

以下是一个选项:

df.loc[df.groupby('id')['taken'].transform(lambda x: x.diff().ne(0)) & df['taken'].eq(1)]

输出:

id  time  taken
1   1     2      1
4   1     5      1
6   2     7      1
8   2     9      1

相关问题