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

Pandas循环计算MAPE抛出KeyError:0错误如何解决

错误原因

你的代码存在两个直接触发报错、且逻辑不符合预期的问题:

  1. 初始化的mape_hm是无任何行列的空DataFrame,执行mape_hm[i][e]赋值时,Pandas会优先查找列名为i(第一次循环i=0)的列,空表不存在该列,直接抛出KeyError:0。
  2. 就算绕开空表赋值问题,原有逻辑既没有处理MAPE结果和原表的行对齐,也没有按照要求生成带MAPE_前缀的列名,最终输出结构和预期不符。
  3. 你要求保留lista_com的嵌套列表结构,原有循环的索引遍历逻辑本身没问题,问题出在赋值和结果拼接的环节。
修正代码

完全保留你给定的嵌套列表lista_com结构、双层循环框架,只修正赋值和结果拼接逻辑,代码如下:

import pandas as pd
from sklearn.metrics import mean_absolute_percentage_error

# 原始数据与初始化参数保持原样
df1 = pd.DataFrame({'id' : [1, 2, 1,2], 'plat' : ['and','and','ios','ios'], 'd30_real' : [1.2,1.4,1.5,1.9], 'd3_d30':[1.1,1.5,1.5,1.8], 'd7_d30':[1.4,1.5,1.6,1.9], 'd14_d30':[1.2,1.3,1.5,2.0]})
lista_target = ['d30_real']
lista_com = [['d3_d30','d7_d30','d14_d30']]

# 以原始df为基表,保留所有原始字段,避免空表赋值问题
result = df1.copy()

for i in range(len(lista_target)):
    target_col = lista_target[i]
    for e in range(len(lista_com[i])):
        pred_col = lista_com[i][e]
        # 按指定维度分组计算MAPE,重命名为要求的列名
        mape_res = df1.groupby(['id','plat']).apply(
            lambda x: mean_absolute_percentage_error(x[target_col], x[pred_col])
        ).rename(f'MAPE_{pred_col}').reset_index()
        # 按分组键将MAPE结果合并回基表,自动对齐行
        result = result.merge(mape_res, on=['id','plat'], how='left')

运行后得到的result结构和你要求的完全一致,实际计算值如下(你给出的示例为虚拟值,以下为真实计算结果):

id plat  d30_real  d3_d30  d7_d30  d14_d30  MAPE_d3_d30  MAPE_d7_d30  MAPE_d14_d30
0   1  and       1.2     1.1     1.4      1.2     0.083333     0.166667      0.000000
1   2  and       1.4     1.5     1.5      1.3     0.071429     0.071429      0.071429
2   1  ios       1.5     1.5     1.6      1.5     0.000000     0.066667      0.000000
3   2  ios       1.9     1.8     1.9      2.0     0.052632     0.000000      0.052632

说明:当前每个(id, plat)分组仅包含1条样本,因此分组计算的MAPE等价于单条样本的相对误差,符合当前数据场景。

内容的提问来源于stack exchange,提问作者MatmataHi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 11:54:23