pandas中对nan空值的判断

刘超 2月前 ⋅ 500 阅读   编辑

  pandas基于numpy,所以其中的空值nan和numpy.nan是等价的。numpy中的nan并不是空对象,其实际上是numpy.float64对象,所以我们不能误认为其是空对象,从而用bool(np.nan)去判断是否为空值,这是不对的。

一、怎么判断

   对于pandas中的空值,我们该如何判断,并且有哪些我们容易掉进去的陷阱,即不能用怎么样的方式去判断呢?

  1、可以判断pandas中单个空值对象的方式:
  - 利用pd.isnull(),pd.isna();
  - 利用np.isnan();
  - 利用is表达式;
  - 利用in表达式
  - 使用math库的isnan函数

  2、不可以用来判断pandas单个空值对象的方式:
  - 不可直接用==表达式判断;
  - 不可直接用bool表达式判断;
  - 不可直接用if语句判断。

  3、对于同时多个空值对象的判断和处理:
  - 可以用Series对象和DataFrame对象的any()或all()方法;
  - 可以用numpy的any()或all()方法;
  - 不可以直接用python的内置函数any()和all()方法;
  - 可以用Series或DataFrame对象的dropna()方法剔除空值;
  - 可以用Series或DataFrame对象的fillna()方法填充空值。

二、示例:

>>> import pandas as pd
>>> import numpy as np
>>> from math import isnan
>>> 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
>>> isnan(na)
True
>>> # 可以用来判断非空的方式
>>> pd.notnull(na)
False
>>> pd.notna(na)
False
>>> ~np.isnan(na) # 这种小数据量可以,大数据量就报错https://itdiandi.net/view/2874
False
>>> # 不可以直接用来判断的方式,即以下结果和我们预期不一样
... 
>>> na == np.nan
False
>>> bool(na)
True
>>> if na:
...     print('na is not null')
... 
na is not null

>>> # 不可以直接用python内置函数any和all
... 
>>> any([na])
True
>>> all(


Querying for NaN and other names in Pandas


In general, you could use @local_variable_name, so something like

>>> pi = np.pi; nan = np.nan
>>> df = pd.DataFrame({"value": [3,4,9,10,11,np.nan,12]})
>>> df.query("(value < 10) and (value > @pi)")
   value
1      4
2      9
would work, but nan isn't equal to itself, so value == NaN will always be false. One way to hack around this is to use that fact, and use value != value as an isnan check. We have

>>> df.query("(value < 10) or (value == @nan)")
   value
0      3
1      4
2      9

According to this answer you can use:

df.query('value < 10 | value.isnull()', engine='python')

import pandas as pd
import numpy as np

df = pd.DataFrame({'value': [3, 4, 9, 10, 11, np.nan, 12]})
available = df.query("value.notna()")
print(available)


9

You can use the isna and notna Series methods, which is concise and readable.

import pandas as pd
import numpy as np

df = pd.DataFrame({'value': [3, 4, 9, 10, 11, np.nan, 12]})
available = df.query("value.notna()")
print(available)

#    value
# 0    3.0
# 1    4.0
# 2    9.0
# 3   10.0
# 4   11.0
# 6   12.0

not_available = df.query("value.isna()")
print(not_available)

#    value
# 5    NaN
Alternatively, you can use the toplevel pd.isna function, by referencing it as a local variable.

import pandas as pd
import numpy as np


df = pd.DataFrame({'value': [3, 4, 9, 10, 11, np.nan, 12]})
df.query("@pd.isna(value)")

#    value
# 5    NaN

https://stackoverflow.com/questions/26535563/querying-for-nan-and-other-names-in-pandas

三、总结
       numpy.nan是一个numpy.float64的非空对象,所以不能直接用bool表达式去判断,故一切依赖于布尔表达式的判断方式都不行,比如if语句。对于pandas中空值的判断,我们只能通过pandas或者numpy的函数和is表达式去判断,不能用python的内置函数any或all判断。

  比较奇怪的一点是pandas中空值的判断可以用is表达式判断,但是不能用==表达式判断。我们知道,对于is表达式,如果返回True,表示这两个引用指向的是同一个内存对象,即内存地址是一样的,一般同一个对象的不同引用的值也应该是相等的,所以一般is表达式为True,那么==表达式也为True。但是对于numpy.nan对象显然不是这样的,因为其可以用is表达式判断,即当is表达式为True时,但==表达式为False,这说明虽然不同numpy.nan变量引用指向的是同一个内存地址,但是其具有自己的值属性,值是不一样的,所以不能用==来判断,这点需要注意。

四、参考文章
1、https://blog.csdn.net/S_o_l_o_n/article/details/100661937
2、https://www.cnblogs.com/itdyb/p/5806688.html


注意:本文归作者所有,未经作者允许,不得转载

全部评论: 0

    我有话说: