pandas解析字典类型列生成新列时触发ValueError的解决方案
错误产生原因
apply(axis=1)遍历DataFrame时,传入lambda函数的参数x是逐行返回的整行Series对象,并非'str'列的单个元素。执行pd.notnull(x)时,会对该行所有字段逐一做非空判断,返回一个和列数等长的布尔Series。Pandas无法直接判定多值Series的整体真假,因此会抛出「真值歧义」的ValueError。- 原代码lambda分支内的
d['str'].str['a']是对全列'str'做键提取,返回的是整列结果,和逐行赋值的逻辑不匹配,就算跳过报错也无法得到预期结果。 - 示例代码未导入numpy库,直接运行会先触发
np.nan未定义的NameError,属于笔误。
正确实现方案
优先使用Pandas原生的str访问器实现,无需手写apply,性能更高且会自动跳过空值:
import pandas as pd import numpy as np d = pd.DataFrame({ 'id': [0, 1, 2], 'str': [{'a':'1'},{'a':'2'},np.nan] }) # 直接提取字典列中key为'a'的值,空值自动保留 d['new_col'] = d['str'].str['a']
执行后得到的结果如下:
| id | str | new_col |
|---|---|---|
| 0 | {'a': '1'} | 1 |
| 1 | {'a': '2'} | 2 |
| 2 | NaN | NaN |
如果需要保留apply写法(比如后续要追加复杂逐行逻辑),需要修正判断和取值的粒度,针对单行的目标字段做操作:
d['new_col'] = d.apply( lambda row: row['str'].get('a') if pd.notnull(row['str']) else row['str'], axis=1 )
写法注意点:
- 参数命名为
row明确语义,代表当前遍历到的整行数据 - 非空判断针对
row['str'](当前行的字典字段)做判断,不会返回多值布尔序列 - 取值时针对当前行的字典字段做key提取,不要引用整个DataFrame的全列数据。
内容的提问来源于stack exchange,提问作者kms
相关产品推荐
相关产品推荐

