pandas中NaN空值判断的正确与错误方式及常见陷阱
本文详解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,将修改作用于原数据
以上为个人经验总结,希望能给大家一个参考,也希望大家多多支持本站。如有错误或未考虑完全的地方,望不吝赐教。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













