pandas中NaN空值判断的正确与错误方式及常见陷阱

宋时安
宋时安
发布时间:2026-10-12 | 3人浏览过
原创

本文详解pandas中NaN空值的判断方法,指出pd.isnull、pd.isna及np.isnan为正确方式,而直接使用==、bool或if语句会导致误判。文章通过示例对比is与==表达式的差异,并补充了查找、填充及删除空值的完整操作指南,帮助开发者避免常见陷阱。

pandas底层基于numpy构建,因此其中的空值NaN与numpy.nan在本质上是等价的。需要注意的是,numpy中的nan并非表示“空对象”,它实际上是一个numpy.float64类型的数值对象。因此,不能错误地将其视为空对象,进而使用bool(np.nan)来检测是否为空,这种做法是错误的。

面对pandas中的空值,我们应当如何准确判断?同时存在哪些容易踩中的陷阱,即哪些方法是不适用于判断空值的?

以下是判断pandas中单个空值对象的有效方法:

1、使用pd.isnull()或pd.isna()函数;

2、使用np.isnan()函数;

3、使用is身份运算符;

4、使用in成员运算符。

以下方法不能用于判断pandas中的单个空值对象:

1、不能直接使用==相等运算符进行判断;

2、不能直接使用bool()函数进行判断;

3、不能直接在if语句的条件判断中使用。

具体示例如下:

import pandas as pd
import numpy as np 
na=np.nan 
# 可以用来判断空值的方式
pd.isnull(na) # True
pd.isna(na) # True
np.isnan(na) # True
na is np.nan # True
na in [np.nan] # True 
 
# 不可以直接用来判断的方式,即以下结果和我们预期不一样
na == np.nan # False
bool(na) # True
if na:
  print('na is not null') # Output: na is not null 
 
# 不可以直接用python内置函数any和all
any([na]) # True
all([na]) #True

总结

numpy.nan是一个numpy.float64类型的非空数值对象,因此不能直接通过bool表达式来判断其状态。这意味着所有依赖布尔表达式逻辑的判断方式均无效,例如在if语句中直接使用nan作为条件。

对于pandas中的空值判断,必须通过pandas或numpy提供的专用函数(如isnull、isnan)以及is身份运算符来进行。切勿使用Python的内置函数any或all来直接判断空值。

一个值得注意的现象是,pandas中空值的判断可以使用is表达式,却不能使用==表达式。通常,如果is表达式返回True,意味着两个引用指向同一个内存对象,此时==表达式也应为True。

然而,对于numpy.nan对象,情况并非如此。is表达式可以正确判断为True(因为所有NaN实例在特定上下文中可能指向同一内存地址或被视为同一标识),但==表达式却返回False。这说明尽管不同变量引用的内存地址可能相同,但其值属性并不相等,因此不能使用==进行判断,这一点需要特别留意。

补充内容:Pandas与Numpy中数据空值的处理操作:判断、查找、填充及删除

本文整理了数据中空值的常见处理操作,主要内容包括:

为了便于描述,定义本文示例数据为如下结构:

df = pd.DataFrame([[1, np.nan], [np.nan, 4], [5,6],[np.nan,7]],columns=["A","B"])
df #定义示例数据df

判断数据中是否存在空值

pandas isnull()函数

df.isnull()  #返回df中各元素是否为空的同df大小的数据框 
df["A"].isnull() #判断A列中空值情况 
df[["A","B"]].isnull() # 指定多列进行空值判断,对于本文实例,下述代码效果同df.isnull() 

pandas notnull()函数

df.notnull()  #判断df中各元素是否 不是 空值 
df["A"].isnull() #判断A列中非空值情况 
df[["A","B"]].isnull() # 指定多列进行非空值判断,对于本文实例,下述代码效果同df.notnull() 

numpy np.isnan() 函数

np.isnan(df)  # 等同于df.isnull() 
np.isnan(df["A"])  # 等同于 df["A"].isnull() 
np.isnan(df[["A","B"]]) # 等同于 df[["A","B"]].isnull()

统计空值或非空值的数量

df.isnull().sum() # 统计每列的空值数量 
df.notnull().sum() # 统计每列的非空值数量 
 
df["A"].count()   # A列 非空数量
df.count()     # 统计所有列的非空值数量
df.count(axis=1)  # 每行非空值数量,axis=1 
df["A"].sum()   # A列 元素数值之和

根据空值条件筛选数据

# 筛选出A列为空的所有行
df[df.A.isnull()]  
df[df["A"].isnull()] 
 
# 筛选出A列非空的所有行
df[df.A.notnull()]  
df[df["A"].notnull()]    
 
# 筛选出df中存在空值的行
df[df.isnull().values==True] 

查找空值所在的索引

np.where(np.isnan(df))  # df中空值所在的行索引及列索引 
np.where(np.isnan(df.A))  # df中A列空值所在的行索引

删除空值 dropna()函数

df.dropna()  # 删除存在空值的行,默认axis=0按行,how=any每行存在一个空值就执行删除行操作 
df.dropna(axis=1) # 删除存在空值的列 
df.dropna(how="all") # 删除所有列都为空值的特定行 
df.dropna(how = "any")  # 删除存在空值的行
 
# 对特定列空值进行删除 
df.dropna(how="any",subset=["A"]) # 删除A列中存在空值的行
 df.dropna(how="any",subset=["A","B"]) # 删除A,B列中只要有一列存在空值的行
 
#将删除操作作用于原数据,修改替换原数据
 df.dropna(how="all",subset=["A","B"],inplace=True) # 删除A,B列都为空值的行,并替换原数据

填充空值fillna()函数

# 用指定的数字来填充
df.fillna(0)  # 用0来填充df中的空值
 
# 用指定的函数统计值来填充
df.fillna(df.mean()) # 用df中数据的平均值来填充空值 
df.fillna(df.mean()["A"])  #指定用A列数据均值来填充df中空值 
df.fillna(df.sum())  # 用df中数据的和来填充空值
 
# 用字典来填充
values = {'A': 0, 'B': 1}  # A列空值用0填充,B列空值用1填充
df.fillna(value=values)  
 
# 用指定字符串来填充空值
df.fillna("unkown")
 
# 不同的填充方式{‘backfill', ‘bfill', ‘pad', ‘ffill', None}
# 每列的空值,用其列下方非空数值填充
df.fillna(method="backfill") 
df.fillna(method="bfill")  # 同backfill
# 每列的空值,用其所在列上方非空数值填充,若上方没有元素,保持空值
df.fillna(method="ffill") 
df.fillna(method="pad")   # 同 ffill
 
#limit参数设置填充空值的最大个数
df.fillna(0,limit=1) # 每列最多填充1个空值,超过范围的空值依然为空
 
#inplace参数空值是否修改原数据df
df.fillna(0,inplace=True) # inplace为true,将修改作用于原数据

以上为个人经验总结,希望能给大家一个参考,也希望大家多多支持本站。如有错误或未考虑完全的地方,望不吝赐教。

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表