Pandas按3列分组新增列 计算国家-类别对应大区的数值贡献占比
问题描述
现有如下Pandas DataFrame(变量名df):
Region Country Category Number 0 NA CA A 2 1 NA CA B 1 2 NA US A 2 3 NA US B 3 4 NA MX A 2 5 NA MX B 1 0 EU FR A 2 1 EU FR B 1 2 EU NL A 1 3 EU NL B 2 4 EU DK A 1 5 EU DK B 2
需求为新增一列,存储每个「国家-类别」组合的Number值,在所属大区同类别总数值中的相对贡献占比。
计算规则示例:NA大区CA国家A类别的贡献值 = 2/(NA大区所有国家A类别的Number总和) = 2/(2+2+2) ≈ 0.33
期望输出效果如下:
Region Country Category Number Contribution 0 NA CA A 2 0.33 1 NA CA B 1 0.20 2 NA US A 2 0.33 3 NA US B 3 0.60 4 NA MX A 2 0.33 5 NA MX B 1 0.20 0 EU FR A 2 0.50 1 EU FR B 1 0.20 2 EU NL A 1 0.25 3 EU NL B 2 0.40 4 EU DK A 1 0.25 5 EU DK B 2 0.40
注:示例输出中的Population列为笔误,实际计算逻辑无需该字段。
原实现代码未得到预期结果:
df['Contribution'] = df.groupby(['Region','Country,'Category'])['Number'].apply(lambda x: x*100/x.sum())
错误原因
原代码存在两处问题:
- 分组维度错误:计算同大区同类别的数值总和,仅需按
Region、Category两个字段分组即可。原代码错误将Country加入分组键,导致每个国家-类别组合单独成组,计算出的占比恒为1,完全不符合需求 - 语法错误:分组字段列表中
'Country缺失闭合单引号,运行时会直接触发语法报错
实现方案
使用groupby配合transform方法即可实现,transform会将分组计算的总和按原数据索引对齐返回,直接做除法就能得到每行对应的占比:
# 计算占比 df['Contribution'] = df['Number'] / df.groupby(['Region', 'Category'])['Number'].transform('sum') # 如果需要保留两位小数,加round即可 df['Contribution'] = df['Contribution'].round(2)
运行上述代码后得到的结果与预期完全一致。
内容的提问来源于stack exchange,提问作者Jnams
相关产品推荐
相关产品推荐

