You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas MultiIndex插入分组求和索引层出现NaN问题求解

问题场景

需要在Pandas MultiIndex结构的Warnings、equip两个索引层之间新增索引层,存储每个Warnings层级下count per equip列的求和结果,要求最终0级索引Warnings的条目数量不变,示例中三个warning对应的预期求和值分别为103、109、123。

初始测试数据构造代码:

import pandas as pd
idx = pd.MultiIndex.from_product([['warning1', 'warning2', 'warning3'],
                                  ['ff0001', 'ff0002', 'ff0003']],
                                 names=['Warnings', 'equip'])
col = ['count per equip']
df = pd.DataFrame([100,2,1,44,45,20,25,98,0], idx, col)

原有错误实现运行后所有数值变为NaN,代码如下:

df = df.assign(total=df.groupby(level=[0]).size()).set_index('total', append=True).reorder_levels(['Warnings','total','equip'])
错误原因
  • 聚合方法用错:groupby(level=[0]).size()统计的是每个分组的行数,本示例中每个Warnings下固定3个equip,返回值全为3,完全不是count per equip列的求和结果
  • 结果索引无法对齐:普通groupby聚合返回的结果是按Warnings去重后的聚合值,索引只有Warnings一层,直接assign到原表时无法和原表的双层索引匹配,导致生成的total列全为NaN,后续设为索引后自然所有数据行错位显示为NaN。
正确实现代码

使用transform执行分组求和,该方法会返回和原表长度完全一致、索引逐行对齐的聚合结果,再追加为索引层调整顺序即可:

# 逐行匹配对应Warnings分组的求和值
df['total'] = df.groupby(level='Warnings')['count per equip'].transform('sum')
# 将total追加为索引层,调整索引顺序到Warnings和equip之间
df = df.set_index('total', append=True).reorder_levels(['Warnings', 'total', 'equip'])

运行后输出结果完全符合预期:

count per equip
Warnings total equip                
warning1 103   ff0001            100
             ff0002              2
             ff0003              1
warning2 109   ff0001             44
             ff0002             45
             ff0003             20
warning3 123   ff0001             25
             ff0002             98
             ff0003              0

内容的提问来源于stack exchange,提问作者Pedro de Sá

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 04:54:37