Pandas DataFrame分组内百分比计算实现问题
按Team和Month分组计算Status占比
原始数据与尝试代码
原始DataFrame代码
import pandas as pd # 创建DataFrame df = pd.DataFrame({'team': ['A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B'], 'status':['yes','yes','no','no','yes','no','no','yes','no','yes'], 'month':['m1','m2','m3','m2','m1','m3','m2','m1','m3','m1'], 'points': [12, 29, 34, 14, 10, 11, 7, 36, 34, 22]}) # 查看DataFrame print(df)
已尝试的代码
x = df.groupby(['team','month','status']).size().reset_index().rename(columns={0:'cnt'}).pivot(index='team',columns=['month','status']) x = x.fillna(0) x
需求说明
需要按team和month分组,计算每个分组内status为yes和no的占比,示例如下:
- Team A的m1组:yes占100%,no占0%
- Team A的m2组:yes占100%,no占0%
- Team A的m3组:yes占50%,no占50%
Team B同理。
解决方案
可以通过分组计数后求占比的方式实现,以下是两种简洁的实现方法:
方法一:高效分组计算(推荐)
先统计每个(team, month, status)组合的数量,再除以对应(team, month)组的总数得到占比,最后整理成宽表格式:
# 1. 统计各组合的计数 counts = df.groupby(['team', 'month', 'status']).size().rename('count') # 2. 计算每个team-month组内的占比(转成百分比) percentages = counts / counts.groupby(level=['team', 'month']).sum() * 100 # 3. 转成宽表,缺失值补0(和你尝试的结构一致) result = percentages.unstack(['month', 'status']).fillna(0) print(result)
执行后输出结果:
cnt month m1 m2 m3 status yes no yes no yes no team A 100.0 0.0 100.0 0.0 50.0 50.0 B 100.0 0.0 0.0 100.0 0.0 100.0
方法二:基于transform的直观实现
在原始数据上通过transform直接计算每组总数,再求占比:
# 计算每个(team, month, status)的计数 df['group_count'] = df.groupby(['team', 'month', 'status'])['team'].transform('size') # 计算每个(team, month)的总计数 df['total_count'] = df.groupby(['team', 'month'])['team'].transform('size') # 计算百分比 df['percentage'] = (df['group_count'] / df['total_count']) * 100 # 去重并转成宽表 result = df[['team', 'month', 'status', 'percentage']].drop_duplicates() result_pivot = result.pivot(index='team', columns=['month', 'status'], values='percentage').fillna(0) print(result_pivot)
两种方法都能得到符合需求的占比结果,方法一无需修改原始DataFrame,效率更高;方法二更直观,适合理解分组逻辑。
内容的提问来源于stack exchange,提问作者Nabi Shaikh
相关产品推荐
相关产品推荐

