Pandas apply返回多值:返回2个正常、3个报错的原因排查
问题根源分析
这个问题我之前也碰到过,本质是你用的Python 2.7.14对应的旧版本pandas,对df.apply(axis=1)返回值的处理逻辑存在差异:
- 当返回1个值时,
apply生成一维Series,直接赋值给单个列完全没问题; - 当返回2个值的列表时,pandas会自动把每个列表转成
Series,最终组合成二维DataFrame,所以能直接匹配两列赋值; - 但返回3个及以上值的列表时,旧版本pandas不会自动将列表展开为多列,而是返回一个每个元素都是列表的一维
Series。这时你要把这个Series赋值给三列,pandas没法把单个列表元素映射到多个列,就会抛出ValueError或KeyError。
解决方案
核心思路是让apply的返回结果能被pandas识别为二维结构(即DataFrame),有两种简单的实现方式:
方式1:让somefunc返回pd.Series而非列表
直接修改函数的返回值类型,把列表包装成Series,这样apply会自动将所有行的Series组合成DataFrame,完美匹配多列赋值需求:
import pandas as pd def somefunc(input1, input2): output1 = 1 output2 = 2 output3 = 3 return pd.Series([output1, output2, output3]) # 关键修改:返回Series d = {'col1': ['A1', 'B1'], 'col2': ['A2', 'B2']} df = pd.DataFrame(data=d) df[['col3', 'col4', 'col5']] = df.apply(lambda x: somefunc(x['col1'], x['col2']), axis=1) print df
方式2:在apply后显式转换为DataFrame
如果不想修改somefunc的返回逻辑,可以在apply的结果上再调用apply(pd.Series),把每个列表元素转成Series进而生成DataFrame:
import pandas as pd def somefunc(input1, input2): output1 = 1 output2 = 2 output3 = 3 return [output1, output2, output3] d = {'col1': ['A1', 'B1'], 'col2': ['A2', 'B2']} df = pd.DataFrame(data=d) # 先将apply结果转换为DataFrame再赋值 result_df = df.apply(lambda x: somefunc(x['col1'], x['col2']), axis=1).apply(pd.Series) df[['col3', 'col4', 'col5']] = result_df print df
补充说明
你提到实际场景中somefunc会创建临时df2后删除以节省内存,这两种方案都不会影响这个逻辑——只要函数最终返回正确的Series或列表即可,临时数据的清理逻辑可以保留。
内容的提问来源于stack exchange,提问作者sinB
相关产品推荐
相关产品推荐

