pandas按州分组DataFrame应用累计平均病例公式报KeyError 0
报错定位与修复方案
触发KeyError:0的核心原因
该报错并非递推公式逻辑错误,而是pandas索引规则使用不当导致:
- 预处理阶段执行的
dropna、行筛选操作默认保留原DataFrame的原有索引,不会自动将索引重排为从0开始的连续整数序列。 - 递推循环中使用的
df.loc[i, 列名]方法,是按索引标签匹配行,而非按行的物理位置取值。当循环从i=0开始查找标签为0的行时,如果当前DataFrame的索引标签集合中不存在0值,就会直接抛出KeyError: 0。 - 即使索引问题解决,现有循环还存在隐含逻辑缺陷:未按州分组做计算隔离,跨州边界行会错误引用上一个州的最后一行的Cases、Avg day of case值做递推,计算结果完全不符合业务规则。
具体修复步骤
第一步:重置连续索引,解决KeyError报错
在所有预处理逻辑的最后追加一行代码,将索引重置为从0开始的连续整数,彻底消除标签匹配错位的问题:
df = df.reset_index(drop=True)
执行后df.loc[0]、df.loc[1]可以准确匹配到第一行、第二行数据,KeyError报错会直接消失。
第二步:修正递推计算的分组隔离逻辑
按州维度单独做逐行递推,避免跨州取值。可以选择两种实现方式:
- 轻量修改原循环,增加跨州判断跳过计算:
for i in range(1, len(df)): # 遇到不同州的行,直接跳过(首行的初始值已经提前赋值正确) if df.loc[i, 'state'] != df.loc[i-1, 'state']: continue # 原有递推公式保留不变 x = (((df.loc[i, 'Cases'] - df.loc[i-1, 'Cases']) * (df.loc[i, 'Day'] - df.loc[i-1, 'Avg day of case'])) / (df.loc[i, 'Cases'])) + (df.loc[i-1, 'Avg day of case']) df.loc[i, 'Avg day of case'] = round(x, 2) - 效率更优的分组apply方案,避免全局循环的性能损耗:
def _calc_group_avg(group_df): for row_idx in range(1, len(group_df)): prev_row = group_df.iloc[row_idx - 1] curr_row = group_df.iloc[row_idx] calc_val = (((curr_row['Cases'] - prev_row['Cases']) * (curr_row['Day'] - prev_row['Avg day of case'])) / curr_row['Cases']) + prev_row['Avg day of case'] group_df.iloc[row_idx, group_df.columns.get_loc('Avg day of case')] = round(calc_val, 2) return group_df # 按州分组执行计算 df = df.groupby('state', group_keys=False).apply(_calc_group_avg)
额外校验提醒
递推公式成立的前提是
Cases列存储的是累计病例数,而非当日新增病例数。可以提前校验Cases列是否为单调不减序列,符合累计值特征后再执行计算,避免结果偏差。
内容的提问来源于stack exchange,提问作者user15288243
相关产品推荐
相关产品推荐

