pandas groupby有条件的

时间:2018-04-03 18:59:09

标签: python pandas pandas-groupby

我有这个:

IDS    CR_EARNED    TYPE    TOT_ALL_TYPES
001       3          A          7
001       3          A          7
001       1          B          7
002       3          A          6
002       3          A          6
003       2          C          8
003       4          C          8
003       2          A          8

TOT_ALL_TYPES是我创建的一列,通过执行以下操作,为每个ID的所有TYPE CR_EARNED求和:

df['TOT_ALL_TYPES'] = df['CR_EARNED'].groupby(df['IDS']).transform('sum')

接下来,我想创建一个新的列,它将按照ID来表示CR_EARNED,其中TYPE = A或B.结果如下所示:

IDS    CR_EARNED    TYPE    TOT_ALL_TYPES    TOT_AB
001       3          A          7               7
001       3          A          7               7
001       1          B          7               7
002       3          C          6               3
002       3          A          6               3
003       2          C          8               2
003       4          C          8               2
003       2          A          8               2

我将如何做到这一点?

4 个答案:

答案 0 :(得分:3)

IIUC

您可以使用where

df['CR_EARNED'].where(df.TYPE.isin(['A','B']),0).groupby(df['IDS']).transform('sum')
Out[887]: 
0    7
1    7
2    7
3    6
4    6
5    2
6    2
7    2
Name: CR_EARNED, dtype: int64

更多信息

df['CR_EARNED'].where(df.TYPE.isin(['A','B']),0)
Out[890]: 
0    3
1    3
2    1
3    3
4    3
5    0
6    0
7    2
Name: CR_EARNED, dtype: int64

答案 1 :(得分:2)

尝试

df['TOT_AB'] = df['IDS'].map(df[df['TYPE'].isin(['A', 'B'])].groupby('IDS').CR_EARNED.sum())


    IDS CR_EARNED   TYPE    TOT_ALL_TYPES   TOT_AB
0   1   3           A       7               7
1   1   3           A       7               7
2   1   1           B       7               7
3   2   3           A       6               6
4   2   3           A       6               6
5   3   2           C       8               2
6   3   4           C       8               2
7   3   2           A       8               2

答案 2 :(得分:2)

使用pd.factorizenp.bincount + np.where
如果不需要,请删除astype(int)

t = np.in1d(df.TYPE.values, ['A', 'B'])
c = df.CR_EARNED.values
f, u = pd.factorize(df.IDS.values)
df.assign(TOT_AB=np.bincount(f, np.where(t, c, 0))[f].astype(int))

   IDS  CR_EARNED TYPE  TOT_ALL_TYPES  TOT_AB
0    1          3    A              7       7
1    1          3    A              7       7
2    1          1    B              7       7
3    2          3    A              6       6
4    2          3    A              6       6
5    3          2    C              8       2
6    3          4    C              8       2
7    3          2    A              8       2

答案 3 :(得分:1)

如果您计划对这些条件和进行多种变换,首先构建一个中间数据透视表可能会更清楚,然后根据对数据透视表的求和进行分配。

router.delete("/:comment_id", middleware.checkCommentOwnership,function(req,res){
    //find by id and delete
    Comment.findByIdAndRemove(req.params.comment_id, function(err){
        if(err){
            res.redirect("back")
        }else{
            req.flash("success", "Comment Deleted")
            res.redirect("/home/"+req.params.id);
        }
    })
})

如果您希望# Set IDS as the index, and construct an intermediate pivot table df = df.set_index('IDS') totals_by_type = df.pivot_table(index='IDS', columns='TYPE', values='CR_EARNED', aggfunc='sum', fill_value=0) # Get total aggregates df['TOT_ALL_TYPES'] = totals_by_type.sum(axis=1) df['TOT_AB'] = totals_by_type[['A', 'B']].sum(axis=1) 再次成为某列,则可以在此过程结束时使用reset_index

如果您拥有大量数据并希望保留内存,那么可能不是最佳解决方案,因为您需要一个中间表,但如果这不是问题,那么它更具可读性和直接性。

结果输出:

'IDS'
相关问题