为何Pandas str.fullmatch对空值默认返回Else分支?
问题解析:NaN值在np.where与str.fullmatch结合时的不符合预期结果
问题重现
假设DataFrame的df['Old']列数据如下:
0 NaN 1 NEWARK, NJ
执行代码生成新列:
import pandas as pd import numpy as np df['New'] = np.where(df['Old'].str.fullmatch('.*,...') == False, 'Value', 'Else Value')
得到结果:
0 Else Value 1 Else Value
第二行结果符合预期(正则匹配成功,fullmatch返回True,故返回Else Value),但NaN值未匹配正则却也返回Else Value,不符合预期。
原因分析
问题出在NaN值的处理逻辑上:
- 当对NaN调用pandas字符串方法(如
str.fullmatch)时,返回的结果是NaN,而不是布尔值False。 - 在Python中,
NaN == False的比较结果为False(因为NaN与任何值的比较都会返回False,包括和自身比较)。 - 因此
np.where会将NaN对应的条件判定为不满足(条件为False),从而返回第二个参数Else Value。
解决方案
方案1:显式检测NaN并结合正则结果
通过pd.isna()单独检测NaN,再用逻辑或(|)组合正则匹配失败的条件:
df['New'] = np.where(pd.isna(df['Old']) | (df['Old'].str.fullmatch('.*,...') == False), 'Value', 'Else Value')
方案2:利用str.fullmatch的na参数(Pandas 1.1.0+支持)
给str.fullmatch传入na=False,让NaN直接返回布尔值False,后续比较即可符合预期:
df['New'] = np.where(df['Old'].str.fullmatch('.*,...', na=False) == False, 'Value', 'Else Value')
两种方案都能让NaN值对应的df['New']返回Value,第二行保持返回Else Value,符合预期逻辑。
内容的提问来源于stack exchange,提问作者Jonathan Chen
相关产品推荐
相关产品推荐

