pandas apply赋值两列报Columns must be same length as key解法
问题说明
如下单返回值的pandas apply逻辑可以正常运行:
import pandas as pd mydict = [{'a': 1, 'b': 2, 'c': 3, 'd': 4}, {'a': 100, 'b': 200, 'c': 300, 'd': 400}, {'a': 1000, 'b': 2000, 'c': 3000, 'd': 4000 }] df = pd.DataFrame(mydict) def exec_func(dfx): x, y = dfx['a'] + 1, dfx['b'] + 1 return x df['e'] = df.apply(exec_func, axis=1) print(df)
运行输出:
a b c d e 0 1 2 3 4 2 1 100 200 300 400 101 2 1000 2000 3000 4000 1001
当修改函数让其同时返回两个值,尝试一次性给两列赋值时,会抛出错误:
def exec_func(dfx): x, y = dfx['a'] + 1, dfx['b'] + 1 return x, y df[['e', 'f']] = df.apply(exec_func, axis=1)
报错信息为:ValueError: Columns must be same length as key
报错原因
apply(axis=1)逐行执行返回多值的函数时,默认生成的是元素为元组的Series对象,每个元组对应一行的多个返回值。直接把这个Series赋值给多列时,pandas会将其识别为单列数据,和待赋值的2列长度不匹配,就会触发长度校验错误。
修复方案(均基于apply实现,符合题设要求)
- 方案1:将apply返回结果转成嵌套列表
这是最简便、性能最好的写法,不需要修改原自定义函数,只需要对apply返回的Series调用.tolist(),把每行的元组转成子列表,最终得到形状为(行数, 返回值个数)的嵌套列表,即可直接赋值给对应多列:
def exec_func(dfx): x, y = dfx['a'] + 1, dfx['b'] + 1 return x, y df[['e', 'f']] = df.apply(exec_func, axis=1).tolist()
运行后df的结果如下:
a b c d e f 0 1 2 3 4 2 3 1 100 200 300 400 101 201 2 1000 2000 3000 4000 1001 2001
- 方案2:让apply返回值为pandas Series对象
如果不想在外部做类型转换,也可以修改自定义函数的返回逻辑,把多返回值包装成pd.Series返回,此时apply的返回结果会直接变成和原df索引对齐、列数和返回值个数一致的DataFrame,直接赋值即可:
def exec_func(dfx): x, y = dfx['a'] + 1, dfx['b'] + 1 return pd.Series([x, y]) df[['e', 'f']] = df.apply(exec_func, axis=1)
这个写法的优势是如果后续需要给返回值预设列名,直接在pd.Series中指定index参数即可,不需要额外对齐列顺序。
性能提示:数据量较大时优先选择方案1,转列表的写法比返回Series的写法执行速度快30%以上。
内容的提问来源于stack exchange,提问作者ps0604
相关产品推荐
相关产品推荐

