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

给Pandas DataFrame新增多列触发KeyError:原因及解决方法

Pandas apply新增多列触发KeyError的原因与解决方法

先还原你遇到的场景:

这段代码能正常生成x和y列:

import pandas as pd
df = pd.DataFrame(data = {'a': [1, 2, 3], 'b': [4, 5, 6]})
def myfun(a, b):
    return [a + b, a - b]
df[['x', 'y']] = df.apply( lambda row: myfun(row.a, row.b), axis=1)

输出的DataFrame符合预期:

a  b  x   y
0  1  4  5  -3
1  2  5  7  -3
2  3  6  9  -3

但当你尝试用几乎相同的代码新增xx和yy列时:

df[['xx','yy']] = df.apply(lambda row: myfun(row.a, row.b), axis=1)

却弹出了KeyError: "['xx' 'yy'] not in index"的错误,这到底是怎么回事?


错误原因

核心问题出在Pandas对多列赋值的逻辑差异上:

  • 第一次赋值时,df.apply(...)返回的是一个元素为列表的Series。此时Pandas会自动识别到列表的长度和你指定的列数(2列)匹配,于是悄悄把这个Series转换成了一个2列的DataFrame,完成赋值。
  • 但第二次赋值时,因为xx和yy这两列原本不存在于DataFrame中,Pandas的赋值逻辑会先尝试对齐索引——它会把apply返回的Series当成单个值来处理,而单个列表无法匹配两个新列的索引,所以直接抛出了KeyError。

简单说就是:Pandas对“给已有列赋值”和“新增多列”的处理逻辑不一样,前者会自动展开列表型Series,后者不会。


正确的实现方法

这里有几种靠谱的解决方式,按推荐程度排序:

1. 用result_type='expand'参数(最简洁)

直接给apply加上result_type='expand'参数,让它直接返回一个DataFrame,这样Pandas就能明确知道要把每一列对应到你指定的列名上:

df[['xx','yy']] = df.apply(lambda row: myfun(row.a, row.b), axis=1, result_type='expand')

这个参数的作用就是告诉Pandas:把每行返回的列表拆分成单独的列,完美解决新增多列的问题。

2. 显式将Series转为DataFrame

如果你的Pandas版本比较旧(低于0.23,这个版本才引入result_type参数),可以手动把apply返回的Series转换成DataFrame:

df[['xx','yy']] = df.apply(lambda row: myfun(row.a, row.b), axis=1).apply(pd.Series)

apply(pd.Series)会把每个列表元素拆分成DataFrame的一列,再赋值给目标列。

3. 用向量化操作(性能最优)

如果你的函数逻辑像这个例子一样简单(只是加减运算),完全没必要用apply——因为apply是逐行循环,效率很低。直接用Pandas的向量化运算更快:

# 一行搞定
df[['xx','yy']] = df['a'] + df['b'], df['a'] - df['b']

# 或者更清晰的分步写法
df['xx'] = df['a'] + df['b']
df['yy'] = df['a'] - df['b']

这种方式在处理大数据集时,速度会比apply快几个数量级。

4. 用assign链式赋值

如果你习惯用链式操作,不想直接修改原DataFrame,可以用assign方法:

df = df.assign(
    **df.apply(lambda row: myfun(row.a, row.b), axis=1, result_type='expand')
        .rename(columns={0: 'xx', 1: 'yy'})
)

这种方式会返回一个新的DataFrame,原数据不会被修改。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:31:31