Pandas中.apply函数导致整列返回单一值的问题求助
问题:DataFrame处理NaN值时apply函数结果不符合预期
我有这样一个原始DataFrame:
ID | has_id_dummy ----------------------- 340 | NaN NaN | NaN NaN | NaN 200 | NaN
我想要把它转换成这样的目标结果:
ID | has_id_dummy ----------------------- 340 | 1 NaN | 0 NaN | 0 200 | 1
于是我编写了以下自定义函数:
def dummypopulator(x): if x != np.nan: return 1 return 0
并用这段代码调用函数:
df['has_id_dummy'] = df['ID'].apply(dummypopulator)
但结果却完全不符合预期——所有行的has_id_dummy都被设为了1,哪怕ID是NaN的行也没有变成0:
ID | has_id_dummy ----------------------- 340 | 1 NaN | 1 NaN | 1 200 | 1
我还尝试用lambda来间接调用这个函数:
df['has_id_dummy'] = df['ID'].apply(lambda x: dummypopulator(x))
结果还是一样。我感觉自己忽略了某个明显的错误,但就是找不到,求问问题出在哪里?
问题根源
你踩了Python里关于NaN的经典陷阱:NaN和任何值(包括它自己)的比较结果都是False。
举个直观的例子:
np.nan == np.nan的结果是Falsex != np.nan不管x是不是NaN,结果都会是True
所以你的判断条件if x != np.nan:永远成立,不管输入的x是有效ID还是NaN,函数都会返回1,这就是为什么所有行都变成了1。
正确的解决方法
我们需要用专门的NaN检测函数,而不是直接用比较运算符,这里有几种高效的解决方案:
方案1:修改自定义函数
用pandas的pd.notna()或者numpy的np.isnan()来判断,推荐用pandas的方法更贴合DataFrame场景:
import pandas as pd import numpy as np def dummypopulator(x): if pd.notna(x): # 检查x不是NaN return 1 return 0 df['has_id_dummy'] = df['ID'].apply(dummypopulator)
方案2:向量化操作(推荐)
不用写自定义函数,直接用pandas的向量化方法,效率比apply高很多(尤其是数据量大的时候):
df['has_id_dummy'] = df['ID'].notna().astype(int)
notna()会把非NaN值转为布尔值True,NaN转为False,再用astype(int)把True转成1,False转成0,一步到位。
方案3:使用numpy的where函数
也可以用numpy的where函数实现条件赋值:
import numpy as np df['has_id_dummy'] = np.where(pd.notna(df['ID']), 1, 0)
内容的提问来源于stack exchange,提问作者Jasper
相关产品推荐
相关产品推荐

