Pandas GroupBy:布尔标志为True的百分比是多少

3
以下是我的数据的最小示例:
   Id Session Flag toSum
0   1   1      1    2
1   1   2      0    4
2   1   3      0    5
3   1   4      1    6
4   1   5      1    3
5   1   6      0    0
6   1   7      1    1
7   2   1      0    4
8   2   2      1    6
9   2   3      0    2
10  3   1      1    4
11  4   1      1    2
12  4   2      0    1
13  4   3      0    5
14  4   4      1    10

可重现的方法如下:

df = pd.DataFrame({
    'Id': [1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 4, 4, 4, 4],
    'Session':[1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 1, 2, 3, 4],
    'Flag': [1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1],
    'toSum': [2, 4, 5, 6, 3, 0, 1, 4, 6, 2, 4, 2, 1, 5, 10]
})

我想按Id分组,并对Flag列进行聚合,以计算每个Id的标记百分比,同时对toSum列进行求和。
即,生成以下结果:
    Id  Flag %  toSum
0   1   57.14   21
1   2   33.33   12
2   3   100.0   4
3   4   50.0    18

这个如何实现?

2个回答

3

首先聚合 meansum,然后如有必要更改列的格式:

#trick for pass column name with space to agg
df = df.groupby('Id', as_index=False).agg(**{'Flag %':('Flag', 'mean'),
                                             'toSum': ('toSum', 'sum')})

df['Flag %'] = df['Flag %'].mul(100).round(2)
print (df)
   Id  Flag %  toSum
0   1   57.14     21
1   2   33.33     12
2   3  100.00      4
3   4   50.00     18

或者:

df = df.groupby('Id', as_index=False).agg({'Flag': 'mean', 'toSum': sum})

df['Flag'] = df['Flag'].map("{:.2%}".format)
print (df)
   Id     Flag  toSum
0   1   57.14%     21
1   2   33.33%     12
2   3  100.00%      4
3   4   50.00%     18

2
所以,这不是维基百科吗? ;) 简单的groupby+agg已经被看过很多次了,不是吗? - mozway
lambda x: f'{x.mean():.2%}' might be the one-liner solution: df.groupby('Id').agg({'Flag': lambda x: f'{x.mean():.2%}', 'toSum':'sum'}) - ThePyGuy
@ThePyGuy - 是的,但为了性能最好不要在agg中使用复杂的函数,最好是在解决方案之后添加。 - jezrael
1
谢谢。接受此答案是因为其解决方案的效率比其他答案更高。agg**{} 的巧妙技巧也很不错。 - ChrisOram

0

使用带有除法的agg

>>> df.groupby('Id', as_index=False).agg({'Flag': lambda x: round(x.eq(1).sum() / len(x) * 100, 2), 'toSum': sum})
   Id    Flag  toSum
0   1   57.14     21
1   2   33.33     12
2   3  100.00      4
3   4   50.00     18
>>> 

使用百分号:

>>> df.groupby('Id', as_index=False).agg({'Flag': lambda x: f'{round(x.eq(1).sum() / len(x) * 100, 2)}%', 'toSum': sum})
   Id    Flag  toSum
0   1  57.14%     21
1   2  33.33%     12
2   3  100.0%      4
3   4   50.0%     18
>>> 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接