为什么“不是None”不适用于dataframe.loc,但是“!= None”可以正常工作吗?

时间:2019-08-27 06:04:55

标签: python pandas

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

df_ = df.loc[df['entities'] != None]

似乎工作得很好 但是

df_ = df.loc[df['entities'] is not None]

将引发KeyError

  

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

我已经知道解决原始问题的方法了,我很好奇为什么会发生这种情况

2 个答案:

答案 0 :(得分:3)

我有点不高兴,因为我没有使用Pandas的经验,但是没有使用Python的经验……

熊猫通过[]进行的魔术过滤很大程度上基于运算符的重载。在此表达式中:

df.loc[df['entities'] != None]

df['entities']是实现__ne__方法的对象。这意味着您实际上是在做:

df.loc[df['entities'].__ne__(None)]

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

df.loc.__getitem__(df['entities'].__ne__(None))

另一方面,is operator不可重载。没有对象可以实现的__is__方法,因此df['entities'] is not None的评估与Python的核心规则一样,并且由于df['entities']可能实际上不是None,因此其结果表达式为True。因此:

df.loc.__getitem__(True)

这就是错误消息抱怨KeyError: True的原因。

答案 1 :(得分:0)

代替

df_ = df.loc[df['entities'] is not None]

df_ = df.loc[df['entities'] != None]

您宁愿使用

df_ = df.loc[df['entities'].isna()]

因为熊猫中缺失值的表示方式与通常的Python用None(无)表示缺失值的方式不同。特别是您会得到关键错误,因为检查了列系列df['entities']None的身份。在任何情况下,此结果的值为True,因为该系列不是None。然后.loc在行索引中搜索True(在您的情况下不存在),因此引发异常。 !=不会引发此异常,因为相等运算符被pandas.Series重载(否则,您无法通过比较具有固定值的列来构建索引器,如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()

它返回:

Out[18]: 
0     True
1     True
2    False
Name: nulls, dtype: bool

但代码:

df['nulls'] == None

返回

Out[20]: 
0    False
1    False
2    False
Name: nulls, dtype: bool

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

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

对于其他类型的列,缺失值的表示甚至可能不同。例如。如果您使用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

因此,使用isna()而不是!= None还可帮助您避免处理熊猫内部数据表示形式的代码。