Pandas按列apply调用自定义函数返回指定索引DataFrame报错排查
报错原因
pandas中DataFrame.apply(axis=0)是逐列传入数据,lambda接收到的参数是整列的Series对象,不是列名字符串。- 你把长度154、值为1-8随机数的Series作为列索引传给
.loc,pandas会尝试在列名里匹配这154个整数,自然找不到对应列,直接触发KeyError。
修复方案
方案1:修正apply传参逻辑
只需要在lambda中取传入列Series的.name属性,就能拿到真正的列名字符串,原有函数逻辑不需要做任何修改:
import numpy as np import pandas as pd # --------------- 原有数据构造 --------------- frame_exposure = { 'Canada': np.random.randint(1,9,154), 'USA': np.random.randint(1,9,154), 'Mexico': np.random.randint(1,9,154), } df_exposure = pd.DataFrame(frame_exposure,index=np.arange(1960,2114)) frame_expectancy = { 'Canada': np.random.randint(60,80,61), 'USA': np.random.randint(60,80,61), 'Mexico': np.random.randint(60,80,61), } df_life_expectancy = pd.DataFrame(frame_expectancy,index=np.arange(1960,2021)) # --------------- 原有计算函数 --------------- def calc_life_exposure( df_exposure, df_life_expectancy, col, ): exposure_birthyears_percountry = np.empty(len(df_life_expectancy)) for i, birth_year in enumerate(df_life_expectancy.index): life_expectancy = df_life_expectancy.loc[birth_year,col] death_year = birth_year + np.floor(life_expectancy) exposure_birthyears_percountry[i] = df_exposure.loc[birth_year:death_year,col].sum() exposure_birthyears_percountry[i] = exposure_birthyears_percountry[i] + \ df_exposure.loc[death_year+1,col].sum() * \ (life_expectancy - np.floor(life_expectancy)) exposure_birthyears_percountry = pd.Series( exposure_birthyears_percountry, index=df_life_expectancy.index, name=col, ) return exposure_birthyears_percountry # --------------- 修正后的调用代码 --------------- df_test = df_exposure.apply( lambda col_series: calc_life_exposure( df_exposure, df_life_expectancy, col_series.name, # 取Series对应的真实列名 ), axis=0, )
运行后得到的df_test形状和df_life_expectancy完全一致:行索引为1960-2020年,列对应三个国家,符合预期。
方案2:直接拼接单列计算结果(可读性更高)
如果不想记apply的传参规则,可以直接遍历列名计算每个国家的结果,再拼接为完整DataFrame,逻辑更直白不容易出错:
df_test = pd.concat( [calc_life_exposure(df_exposure, df_life_expectancy, col) for col in df_exposure.columns], axis=1 )
注意事项
你提供的示例代码中用np.random.randint生成预期寿命数据,输出全为整数,因此函数里计算最后不满整年的部分暴露量的逻辑永远返回0。如果需要验证这部分逻辑,可以把预期寿命的生成代码替换为随机浮点数实现:
frame_expectancy = { 'Canada': np.random.uniform(60,80,61), 'USA': np.random.uniform(60,80,61), 'Mexico': np.random.uniform(60,80,61), }
内容的提问来源于stack exchange,提问作者Luke Grant
相关产品推荐
相关产品推荐

