pandas df.apply调用返回字典的函数创建新列失败问题求解
错误原因
原有代码无法运行的核心问题有两点:
- 连续三次调用
df.apply(extract_data, axis=1)会触发三次全表逐行遍历,且直接对返回的字典Series取['a']/['p']/['s']属于按列索引取值,和字典的键不匹配,会触发KeyError。 - lambda写法传入了不存在的
x['a']字段作为参数,extract_data需要接收整行Series作为输入,行数据中无a列,必然运行报错。
单遍apply实现方案
只需要调用一次apply,搭配result_type='expand'参数即可自动将每行返回的字典拆分为独立列,仅需一次遍历即可完成三列赋值:
def extract_info(self): def extract_data(row): res = {'A': None, 'P': None, 'S': None} for info in row['Info']: t = info['Type'] if t in res: res[t] = info['Desc'] return res # 自动将返回的字典拆为列,直接拼接回原表 info_cols = self.df.apply(extract_data, axis=1, result_type='expand') self.df = pd.concat([self.df, info_cols], axis=1) return self
高性能优化方案(大数据量优先选)
apply本质是Python层逐行循环,数据量较大时性能较差,可以用pandas原生的矢量化方法实现,性能比apply高5~10倍:
def extract_info(self): # 炸开Info列的列表为单条记录,再把字典拆为普通列 info_long = self.df['Info'].explode().apply(pd.Series) # 行透视成宽表,索引和原表对齐 info_wide = info_long.pivot( index=info_long.index, columns='Type', values='Desc' ) # 拼接回原DataFrame self.df = pd.concat([self.df, info_wide], axis=1) return self
该方案没有手写Python层循环,核心逻辑由pandas C后端实现,数据量越大性能优势越明显,同时不需要手动维护Type和列名的映射关系,后续新增Type类型也能自动生成对应列。
内容的提问来源于stack exchange,提问作者amnesic
相关产品推荐
相关产品推荐

