有没有办法为熊猫分组对象保留每个组的子集?

问题描述 投票:3回答:2

我有一个看起来像这样的数据框:

   id        date  isActive
0   1  2019-01-01         0
1   1  2019-01-02         1
2   1  2019-01-03         1
3   1  2019-01-04         0
4   1  2019-01-05         0
5   2  2019-01-01         0
6   2  2019-01-02         1
7   2  2019-01-03         0
8   2  2019-01-04         1
9   2  2019-01-05         0

我想过滤出每个ID的所有无效(isActive = 0)行,除非该ID的最新行无效。然后,我的数据框应如下所示:

   id        date  isActive
0   1  2019-01-02         1
1   1  2019-01-03         1
2   1  2019-01-04         0
3   1  2019-01-05         0
4   2  2019-01-02         1
5   2  2019-01-04         1
6   2  2019-01-05         0

我以为我应该尝试保留所有活动行,以及与每个ID的最后一组连续isActive值关联的行。为此,我尝试创建一个标志来指示isActive变量何时更改,然后尝试获取每个组的大小:

df['flag'] = df.groupby(['id', df['isActive'].eq(1).cumsum()])['isActive'].transform('size')

然后,我尝试使用applytail来保持满足上述条件的每一行,但我意识到我不能只访问最后一列的flag值:

df.groupby(['ID']).apply(lambda x: (x['Status'].eq(2)) | (x['Status'].tail(x['flag'])))
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

我想我可能会考虑这个问题。有没有更好的方法?

python python-3.x pandas pandas-groupby
2个回答
4
投票

检查isActive是否为0,并从组内的底部获取累积乘积。这将为您提供最后一个0条纹(如果有)的True。将其与1的所有行合并,即可获得总掩码。

# Assumes sorted by date within each id
m = (df['isActive'].eq(0)[::-1].groupby(df['id']).cumprod().sort_index()
     | df['isActive'].eq(1))

df[m]
   id        date  isActive
1   1  2019-01-02         1
2   1  2019-01-03         1
3   1  2019-01-04         0
4   1  2019-01-05         0
6   2  2019-01-02         1
8   2  2019-01-04         1
9   2  2019-01-05         0

0
投票

使用pyjanitor将转换挂接到数据帧,使用shift函数从下一行获取值,并过滤掉任何等于-1的值,因为0-1为负数,但0-0或1-1不会。

import pandas as pd
import pyjanitor

(df.groupby_agg(by='id',
                agg=lambda x: x - x.shift(-1),
                agg_column_name='isActive',
                new_column_name='cumu'
                )
 .fillna(0)
 .query('cumu != -1')
 .reset_index(drop=True)
 .drop('cumu',axis=1)
)



    id  date    isActive
0   1   2019-01-02  1
1   1   2019-01-03  1
2   1   2019-01-04  0
3   1   2019-01-05  0
4   2   2019-01-02  1
5   2   2019-01-04  1
6   2   2019-01-05  0
© www.soinside.com 2019 - 2024. All rights reserved.