pandas按公共索引计算两个DataFrame列比值的报错处理
报错原因
将classif1、classif2设为多层索引后,df1的索引组合存在重复值:同一组classif1+classif2会同时对应SEX_M、SEX_F两条记录,而df2的同组索引是唯一值(仅对应SEX_T维度的汇总值)。pandas做索引对齐的算术运算时,不允许非唯一的多层索引直接做匹配计算,因此抛出ValueError: cannot handle a non-unique multi-index!错误。
解决方法
两个DataFrame仅需按classif1、classif2两个字段匹配对应总数值,不需要对齐sex字段,也不需要强行设置公共索引做运算,以下两种写法都可以直接得到正确结果:
- 方法1:映射匹配(运算效率更高)
把df2转为「(classif1, classif2) : obs_value」的字典,逐行匹配做除法即可,不需要修改原表结构:
# 构建分组到总数值的映射 total_value_map = df2.set_index(['classif1', 'classif2'])['obs_value'].to_dict() # 逐行匹配计算占比 df1['Percentage_of_total'] = df1.apply( lambda x: x['obs_value'] / total_value_map[(x['classif1'], x['classif2'])], axis=1 )
- 方法2:表合并后计算(逻辑更直观)
先把df2的数值列重命名后,按两个公共维度左连接到df1,计算完占比后删掉临时的总数值列即可:
# 提取df2需要的字段并重命名数值列 df2_ref = df2[['classif1', 'classif2', 'obs_value']].rename(columns={'obs_value': 'total_obs'}) # 左连接匹配总数值 df1 = df1.merge(df2_ref, on=['classif1', 'classif2'], how='left') # 计算占比 df1['Percentage_of_total'] = df1['obs_value'] / df1['total_obs'] # 删除临时列 df1.drop(columns='total_obs', inplace=True)
两种方法运行后得到的Percentage_of_total列结果完全一致,比如SEX_M+ECO_SECTOR_TOTAL的占比约为0.659,SEX_F+ECO_SECTOR_TOTAL的占比约为0.341,符合分性别数值除以总数值的计算逻辑。
内容的提问来源于stack exchange,提问作者A.N.
相关产品推荐
相关产品推荐

