如何在Pandas DataFrame中新增列展示分组/子组基于值总和的排名
如何在Pandas DataFrame中新增列展示分组/子组基于值总和的排名
这问题我之前处理类似需求时也碰到过,核心思路其实很清晰:先算出每个(group, subgroup)组合的总值,给这些总值排好名,最后把排名映射回原数据的每一行就行。我结合你的示例给你一步步拆解:
首先先重现你的示例数据:
import pandas as pd df = pd.DataFrame({ "group": ["a", "a", "a", "a", "a", "b", "b", "b", "b", "b","c"], "subgroup": ["i","ii","i","ii","i","ii","i","ii","i","ii","ii"], "value": [2, 4, 2, 3, 5, 1, 2, 4, 1, 5, 11] })
步骤1:计算每个分组的总值
我们用groupby按group和subgroup分组,对value求和,转成DataFrame方便后续处理:
# 计算每个(group, subgroup)的value总和 group_totals = df.groupby(['group', 'subgroup'])['value'].sum().reset_index(name='total_value')
这时候group_totals的结果是:
| group | subgroup | total_value |
|---|---|---|
| a | i | 9 |
| a | ii | 7 |
| b | i | 3 |
| b | ii | 10 |
| c | ii | 11 |
步骤2:给分组总值计算排名
我们需要按总值从大到小排名(1为最高),用Pandas的rank方法,设置ascending=False表示降序,转成整数让排名更直观:
# 按总值降序排名,1对应最大的总值 group_totals['rank'] = group_totals['total_value'].rank(ascending=False, method='min').astype(int)
这里的method='min'是为了处理并列场景(如果多个组总值相同,会给它们分配相同的最小排名),你的示例里没有并列,但加上后代码更通用。现在group_totals就有了我们需要的rank列:
| group | subgroup | total_value | rank |
|---|---|---|---|
| a | i | 9 | 3 |
| a | ii | 7 | 4 |
| b | i | 3 | 5 |
| b | ii | 10 | 2 |
| c | ii | 11 | 1 |
步骤3:把排名合并回原DataFrame
用merge方法,根据group和subgroup两个字段匹配,把rank列映射到原数据的每一行:
# 合并排名到原数据 result = df.merge(group_totals[['group', 'subgroup', 'rank']], on=['group', 'subgroup'], how='left')
现在你可以打印result,就得到了和你预期完全一致的输出:
print(result.to_markdown(index=False))
输出表格:
| group | subgroup | value | rank |
|---|---|---|---|
| a | i | 2 | 3 |
| a | ii | 4 | 4 |
| a | i | 2 | 3 |
| a | ii | 3 | 4 |
| a | i | 5 | 3 |
| b | ii | 1 | 2 |
| b | i | 2 | 5 |
| b | ii | 4 | 2 |
| b | i | 1 | 5 |
| b | ii | 5 | 2 |
| c | ii | 11 | 1 |
如果你喜欢更简洁的链式写法,也可以把步骤合并成一行(可读性稍弱,但代码更紧凑):
result = df.merge( df.groupby(['group', 'subgroup'])['value'] .sum() .reset_index(name='total') .assign(rank=lambda x: x['total'].rank(ascending=False, method='min').astype(int)) [['group', 'subgroup', 'rank']], on=['group', 'subgroup'], how='left' )
这个方法效率很高,因为groupby和merge都是Pandas优化后的操作,即使处理大数据量也能快速完成。
备注:内容来源于stack exchange,提问作者nikto
相关产品推荐
相关产品推荐

