为什么“不是无”与 dataframe.loc 一起工作,但“!=无”工作正常?

Rol*_*ong 5 python pandas

我目前正在使用 Pandas 数据框,我想选择数据框中没有 None 实体属性的所有数据条目。

df_ = df.loc[df['entities'] != None]
Run Code Online (Sandbox Code Playgroud)

似乎工作得很好但是

df_ = df.loc[df['entities'] is not None]
Run Code Online (Sandbox Code Playgroud)

将引发 KeyError 是

文件“pandas_libs\index.pyx”,第 107 行,>pandas._libs.index.IndexEngine.get_loc 文件“pandas_libs\index.pyx”,第 128 行,>pandas._libs.index.IndexEngine.get_loc 文件“pandas_libs\ index_class_helper.pxi”,第 91 行,在 >pandas._libs.index.Int64Engine._check_type KeyError: True

好吧,我已经知道我原来的问题的解决方案,我只是好奇为什么会发生这种情况

jot*_*tbe 5

代替

df_ = df.loc[df['entities'] is not None]
Run Code Online (Sandbox Code Playgroud)

或者

df_ = df.loc[df['entities'] != None]
Run Code Online (Sandbox Code Playgroud)

你应该使用

df_ = df.loc[df['entities'].isna()]
Run Code Online (Sandbox Code Playgroud)

因为pandas 中缺失值的表示与通常的python 用None 表示缺失值的方式不同。特别是您会收到关键错误,因为df['entities']检查列系列的身份与None. 这True在任何情况下都为 ,因为该系列不是None。然后.loc在行索引中搜索True,这在您的情况下不存在,因此会引发异常。!=不会导致引发此异常,因为相等运算符被重载pandas.Series(否则您无法通过将列与固定值(如 in df['name'] == 'Miller')进行比较来构建索引器)。此重载方法执行逐元素比较,并且本身返回一个索引器,该索引器与.loc方法。只是结果可能不是你想要的。

例如,如果你这样做

import pandas as pd
import numpy as np
df= pd.DataFrame(dict(x=[1,2,3], y=list('abc'), nulls= [None, np.NaN, np.float32('inf')]))

df['nulls'].isna()
Run Code Online (Sandbox Code Playgroud)

它返回:

Out[18]: 
0     True
1     True
2    False
Name: nulls, dtype: bool
Run Code Online (Sandbox Code Playgroud)

但代码:

df['nulls'] == None
Run Code Online (Sandbox Code Playgroud)

返回

Out[20]: 
0    False
1    False
2    False
Name: nulls, dtype: bool
Run Code Online (Sandbox Code Playgroud)

如果查看列中存储的对象的数据类型,您会发现它们都是浮点数:

df['nulls'].map(type)
Out[19]: 
0    <class 'float'>
1    <class 'float'>
2    <class 'float'>
Name: nulls, dtype: object
Run Code Online (Sandbox Code Playgroud)

对于其他类型的列,缺失值的表示甚至可能不同。例如,如果您使用Int64列,它看起来像这样:

df['nulls_int64']= pd.Series([None, 1 , 2], dtype='Int64')
df['nulls_int64'].map(type)
Out[26]: 
0    <class 'float'>
1      <class 'int'>
2      <class 'int'>
Name: nulls_int64, dtype: object
Run Code Online (Sandbox Code Playgroud)

因此,使用isna()代替!= None还可以帮助您保持代码干净,以免处理熊猫内部数据表示。


dec*_*eze 5

我在这里有点冒险,因为我没有 Pandas 的经验,但有 Python\xe2\x80\xa6 的经验

\n\n

Panda 的神奇过滤[]很大程度上基于运算符重载。在这个表达式中:

\n\n
df.loc[df[\'entities\'] != None]\n
Run Code Online (Sandbox Code Playgroud)\n\n

df[\'entities\']是一个实现该__ne__方法的对象。这意味着你本质上是在做:

\n\n
df.loc[df[\'entities\'].__ne__(None)]\n
Run Code Online (Sandbox Code Playgroud)\n\n

正在df[\'entities\'].__ne__(None)产生一些新的魔法条件对象。该df.loc对象实现了__getitem__重载下[]标语法的方法,因此整个事情本质上是:

\n\n
df.loc.__getitem__(df[\'entities\'].__ne__(None))\n
Run Code Online (Sandbox Code Playgroud)\n\n

另一方面,is运算符不可重载。__is__对象无法实现任何方法,因此df[\'entities\'] is not None按照 Python 的核心规则进行计算,并且由于df[\'entities\']可能实际上不是None,因此该表达式的结果是True。所以就:

\n\n
df.loc.__getitem__(True)\n
Run Code Online (Sandbox Code Playgroud)\n\n

这就是错误消息抱怨KeyError: True.

\n