dtype 比较: == 和 isin 对 “object” 产生不同的结果

dtype comparison: == and isin produce different results for "object"

提问人:cs95 提问时间:6/7/2019 最后编辑:cs95 更新时间:6/7/2019 访问量:4202

问:

最小示例:

df = pd.DataFrame({'x': ['a', 'b', 'c'], 'y': [1, 2, 3], 'z': ['d', 'e', 'f']})
df

   x  y  z
0  a  1  d
1  b  2  e
2  c  3  f

df.dtypes

x    object
y     int64
z    object
dtype: object

这个想法是过滤掉类型的列。我知道这可以通过 来完成,这个问题背后的动机是检查我将要向您展示的内容背后的奇怪行为。objectselect_dtypes

==(因此,)用于比较特定类型。.eq

df.dtypes == object

x     True
y    False
z     True
dtype: bool

但是,不会:isin

df.dtypes.isin([object])
df.dtypes.isin(['object'])

x    False
y    False
z    False
dtype: bool

OTOH,创建一个对象并传递它。np.dtype

df.dtypes.isin([np.dtype('O')])

x     True
y    False
z     True
dtype: bool

np.isin在这里有效,所以没有理由让它表现得有任何不同。

np.isin(df.dtypes, object)
array([ True, False,  True])

np.isin(df.dtypes, 'object')
array([ True, False,  True])

isin仅在检查对象类型时似乎会引起麻烦。 给出预期的结果。df.dtypes.isin(['int'])

顺便说一句,我在 0.24 上运行这些测试。

pd.__version__
'0.24.2'

这是一个错误,还是预期的行为?

蟒蛇 熊猫

评论

0赞 Quang Hoang 6/7/2019
df.dtypes.isin(['object'])在 0.24.2 中产生正确的输出。
1赞 roganjosh 6/7/2019
@QuangHoang显然不在 0.24 中。这个问题的出现是因为我无法在聊天中重现 0.20.3
0赞 G. Anderson 6/7/2019
这对我有用'0.24.2'
0赞 Quang Hoang 6/7/2019
@G.Anderson 0.24.2 仍然在我的计算机上给出了意想不到的答案。isin[object]
0赞 cs95 6/7/2019
@both:你确定吗?我刚刚更新了我的版本。它在 0.24.2 上不起作用。也许是一个回归错误。

答:

7赞 root 6/7/2019 #1

在这种情况下,这归结为依赖哈希表,而在 0.20.3 中,这可能会沿着不同的代码路径使用,并根据您的 python/numpy 版本使用。pandas.Series.isinnp.in1d

请注意,和的哈希值不同,这解释了当前失败的原因:np.dtype('O')object

In [2]: hash(np.dtype('O'))
Out[2]: 7065344498483383396

In [3]: hash(object)
Out[3]: 108607961

看起来正在对对象进行直接的相等性比较,并且与 / 的相等性内置于独立于哈希的定义中。np.in1dobject'object'np.dtype('O')

它还说明了 pandas 的一个更大问题:对于较小的输入情况,比较相同但具有不同哈希值的对象将失败。请考虑以下类:isinisin

class Foo(object):
    def __init__(self, hash_val):
        self.hash_val = hash_val

    def __hash__(self):
        return self.hash_val

    def __eq__(self, other):
        return isinstance(other, Foo)

然后我们得到:

In [5]: s = pd.Series([Foo(0), Foo(1), Foo(2)])

In [6]: s == Foo(3)
Out[6]:
0    True
1    True
2    True
dtype: bool

In [7]: s.isin([Foo(3)])
Out[7]:
0    False
1    False
2    False
dtype: bool

In [8]: np.in1d(s.values, [Foo(3)])
Out[8]: array([ True,  True,  True])

这是一个错误吗?可能,但我猜这将是一个低优先级的项目,因为这是一个极端情况,并且可能以高性能的方式修复(即当前实现有一个注释,表明对象 dtypes 不应该被传递给,因为它可能会引发,所以简单地委派给是行不通的)。np.in1dnp.in1d

评论

3赞 user2357112 6/7/2019
dtype比较是完全疯狂的,不应该像它那样行事,但如果 NumPy 开发人员现在试图改变事情,太多的现有代码会中断。正如本例所示,依赖 dtypes 与不是 实例的对象的比较是一个坏主意。numpy.dtype
0赞 Bill 10/31/2023
仅供参考,2020 年提出了一个与此问题相关的问题:dataframe.dtype.isin() 中的不一致 - 我在同一代码上的不同运行不一致。