首页 > 解决方案 > 如何使用 Pandas 在不同列的标志值之间进行分组?

问题描述

假设我有一个这样的数据框:

日期 is_start is_end
2021-07-16 10:40 错误的 错误的
2021-07-16 10:41 错误的 错误的
2021-07-16 10:42 错误的 错误的
2021-07-16 10:43 真的 错误的
2021-07-16 10:44 错误的 错误的
2021-07-16 10:45 错误的 真的
2021-07-16 10:46 错误的 错误的
2021-07-16 10:47 真的 错误的
2021-07-16 10:48 错误的 错误的
2021-07-16 10:49 错误的 错误的
2021-07-16 10:50 错误的 错误的
2021-07-16 10:51 错误的 真的
2021-07-16 10:52 错误的 错误的
2021-07-16 10:53 错误的 错误的
2021-07-16 10:54 真的 错误的
2021-07-16 10:55 错误的 错误的

我希望能够使用 groupby (或在效率方面类似的东西)在它们各自的 is_start 和 is_end 标志之间(并包括)创建行组。例如:

第 1 组

日期 is_start is_end
2021-07-16 10:43 真的 错误的
2021-07-16 10:44 错误的 错误的
2021-07-16 10:45 错误的 真的

第 2 组

日期 is_start is_end
2021-07-16 10:47 真的 错误的
2021-07-16 10:48 错误的 错误的
2021-07-16 10:49 错误的 错误的
2021-07-16 10:50 错误的 错误的
2021-07-16 10:51 错误的 真的

我希望有一个解决方案,而不是沿着循环使用 iterrows 的路线,但到目前为止,它让我望而却步。

此外...

(但不那么重要)

有一种方法可以单独识别从 2021-07-16 10:54 开始的未完成组也很有用

标签: pythonpandasdataframepandas-groupby

解决方案


使用一些cumsum就可以了。首先在 is_start 上创建一个组 id

df['gr'] = df['is_start'].cumsum()
print(df)
                Date  is_start  is_end  gr
0   2021-07-16 10:40     False   False   0
1   2021-07-16 10:41     False   False   0
2   2021-07-16 10:42     False   False   0
3   2021-07-16 10:43      True   False   1
4   2021-07-16 10:44     False   False   1
5   2021-07-16 10:45     False    True   1
6   2021-07-16 10:46     False   False   1
7   2021-07-16 10:47      True   False   2
8   2021-07-16 10:48     False   False   2
9   2021-07-16 10:49     False   False   2
10  2021-07-16 10:50     False   False   2
11  2021-07-16 10:51     False    True   2
12  2021-07-16 10:52     False   False   2
13  2021-07-16 10:53     False   False   2
14  2021-07-16 10:54      True   False   3
15  2021-07-16 10:55     False   False   3

然后cumsum在 is_end 上再次使用,shift它包括结束行。将其减去之前创建的列 gr 以删除结束后的行。自行相乘。

df['gr'] = (df['gr'] - df['is_end'].cumsum().shift(fill_value=0))*df['gr']
print(df)
                Date  is_start  is_end  gr
0   2021-07-16 10:40     False   False   0
1   2021-07-16 10:41     False   False   0
2   2021-07-16 10:42     False   False   0
3   2021-07-16 10:43      True   False   1
4   2021-07-16 10:44     False   False   1
5   2021-07-16 10:45     False    True   1
6   2021-07-16 10:46     False   False   0
7   2021-07-16 10:47      True   False   2
8   2021-07-16 10:48     False   False   2
9   2021-07-16 10:49     False   False   2
10  2021-07-16 10:50     False   False   2
11  2021-07-16 10:51     False    True   2
12  2021-07-16 10:52     False   False   0
13  2021-07-16 10:53     False   False   0
14  2021-07-16 10:54      True   False   3
15  2021-07-16 10:55     False   False   3

现在要获取组并停止未完成的组,您可以执行以下操作:

for gr, dfg in df.loc[df['gr']>0].groupby('gr'):
    if not dfg['is_end'].any(): print(f'unfinished groupe{gr}', dfg)
    print(f'groupe{gr}', dfg)

注意:这仅在 is_start 之前的 is_end 中没有 True 时才有效


推荐阅读