在Pandas中查询NaN和其他名称
假设我有一个数据表 df
,里面有一列叫 value
,这列里有一些浮点数值,还有一些是 NaN
(表示缺失值)。我想用查询语法找出数据表中那些是 NaN
的部分,应该怎么做呢?
比如,下面这个方法就不行:
df.query( '(value < 10) or (value == NaN)' )
我得到的错误是 name NaN is not defined
(用 df.query('value ==NaN')
也是一样的错误)。
一般来说,有没有办法在查询中使用像 inf
、nan
、pi
、e
这些 numpy 的名称呢?
7 个回答
Pandas在处理数据表时,会用NumPy的nan值来填充空白单元格。结果就是,这种空值有一些奇怪的特性。首先,什么都不等于这种空值,连它自己也不例外。因此,你不能通过检查某个特定的相等性来寻找它。
In : 'nan' == np.nan
Out: False
In : None == np.nan
Out: False
In : np.nan == np.nan
Out: False
不过,由于一个包含np.nan值的单元格不会等于任何东西,包括另一个np.nan值,我们可以检查它是否不等于它自己。
In : np.nan != np.nan
Out: True
你可以利用这个特性,使用Pandas的查询方法,简单地搜索那些在特定列中值不等于它自己的单元格。
df.query('a != a')
或者
df[df['a'] != df['a']]
对于那些value
不为空的行
df.query("value == value")
对于那些value
为空的行
df.query("value != value")
你可以使用 isna
和 notna
这两个方法,它们简单易懂,使用起来也很方便。
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
如果你安装了 numexpr
,那么在使用 .query
的时候需要加上 engine="python"
,这样才能正常工作。numexpr
是 pandas 推荐的工具,可以加快在大数据集上使用 .query
的速度。
available = df.query("value.notna()", engine="python")
print(available)
另外,你也可以使用顶层的 pd.isna
函数,只需将其作为本地变量引用。同样,如果有 numexpr
,在使用时也需要加上 engine="python"
。
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
一般来说,你可以使用 @local_variable_name
,所以像这样
>>> 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
是可以工作的,但 nan
这个值和它自己是不相等的,所以 value == NaN
这个判断永远会是假的。解决这个问题的一种方法是利用这个特性,使用 value != value
来检查是否是 nan
。我们有
>>> df.query("(value < 10) or (value == @nan)")
value
0 3
1 4
2 9
但是
>>> df.query("(value < 10) or (value != value)")
value
0 3
1 4
2 9
5 NaN