比较dtype对象的numpy数组

时间:2018-10-09 06:59:56

标签: python python-3.x numpy

我的问题是“为什么?:”

aa[0]
array([[405, 162, 414, 0,
        array([list([1, 9, 2]), 18, (405, 18, 207), 64, 'Universal'],
      dtype=object),
        0, 0, 0]], dtype=object)

aaa
array([[405, 162, 414, 0,
        array([list([1, 9, 2]), 18, (405, 18, 207), 64, 'Universal'],
      dtype=object),
        0, 0, 0]], dtype=object)

np.array_equal(aaa,aa[0])
False

这些数组完全相同。

我的最小示例不会重现此内容:

be=np.array([1],dtype=object)

be
array([1], dtype=object)

ce=np.array([1],dtype=object)

ce
array([1], dtype=object)

np.array_equal(be,ce)
True

也没有这样做:

ce=np.array([np.array([1]),'5'],dtype=object)

be=np.array([np.array([1]),'5'],dtype=object)

np.array_equal(be,ce)
True

但是,要重现我的问题,请尝试以下操作:

be=np.array([[405, 162, 414, 0, np.array([list([1, 9, 2]), 18, (405, 18, 207), 64, 'Universal'],dtype=object),0, 0, 0]], dtype=object)

ce=np.array([[405, 162, 414, 0, np.array([list([1, 9, 2]), 18, (405, 18, 207), 64, 'Universal'],dtype=object),0, 0, 0]], dtype=object)

np.array_equal(be,ce)
False

np.array_equal(be[0],ce[0])
False

我不知道为什么这些不相等。并添加奖金问题,我如何比较它们?

我需要一种有效的方法来检查aaa是否在aa堆栈中。

由于aaa in aa我没有使用DeprecationWarning: elementwise == comparison failed; this will raise an error in the future.,因为如果有人在想,它仍会返回False


我还尝试了什么?

np.equal(be,ce)
*** ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

np.all(be,ce)
*** TypeError: only integer scalar arrays can be converted to a scalar index

all(be,ce)
*** TypeError: all() takes exactly one argument (2 given)

all(be==ce)
*** TypeError: 'bool' object is not iterable

np.where(be==ce)
(array([], dtype=int64),)

这些,我无法在控制台中运行,全部评估为False,其中一些给出了弃用警告:

import numpy as np

ce=np.array([[405, 162, 414, 0, np.array([list([1, 9, 2]), 18, (405, 18, 207), 64, 'Universal'],dtype=object),0, 0, 0]], dtype=object)

be=np.array([[405, 162, 414, 0, np.array([list([1, 9, 2]), 18, (405, 18, 207), 64, 'Universal'],dtype=object),0, 0, 0]], dtype=object)

print(np.any([bee in ce for bee in be]))

print(np.any([bee==cee for bee in be for cee in ce]))

print(np.all([bee in ce for bee in be]))

print(np.all([bee==cee for bee in be for cee in ce]))

当然other questions告诉我这应该起作用...

3 个答案:

答案 0 :(得分:5)

要在数组之间进行逐元素比较,可以将numpy.equal()与关键字参数dtype=numpy.object一起使用,如下所示:

In [60]: np.equal(be, ce, dtype=np.object)
Out[60]: 
array([[True, True, True, True,
        array([ True,  True,  True,  True,  True]), True, True, True]],
      dtype=object)

PS 已使用NumPy版本1.15.2和Python 3.6.6

检查

编辑

从1.15发行说明开始,

https://docs.scipy.org/doc/numpy-1.15.1/release.html#comparison-ufuncs-accept-dtype-object-overriding-the-default-bool

Comparison ufuncs accept dtype=object, overriding the default bool

This allows object arrays of symbolic types, which override == and 
other operators to return expressions, to be compared elementwise with 
np.equal(a, b, dtype=object).

答案 1 :(得分:2)

您看到的行为已记录在Environment

  

弃用¶

     

...

     

对象数组相等性比较

     

在将来的对象数组比较中,==和np.equal都不会   利用身份检查了。例如:

     
    
      

>

             
        

a = np.array([np.array([1,2,3]),1])

                 

b = np.array([np.array([1,2,3]),1])

                 

a == b

      
    
  
     

始终会返回False(将来还会返回错误),即使   a和b中的数组是同一对象。

     

等于运算符==将来会引发类似np.equal的错误   如果广播或元素比较等失败。

     

与arr ==的比较将来将不会做任何元素   比较,而不只是返回False。代码应使用arr   没有。

     

所有这些更改将在此时提供Deprecation-或FutureWarnings   时间。

到目前为止,如此清晰。是吗?

我们从@ kmario23的答案中可以看到,从15.2版开始,这些更改尚未完全实现。

让情况更糟的是,请考虑以下问题:

>>> A = np.array([None, a])
>>> A1 = np.array([None, a])
>>> At = np.array([None, a[:2]])
>>> 
>>> A==A1
False
>>> A==At
array([ True, False])
>>> 

看起来当前的行为更多是巧合,而不是精心计划的结果。

我怀疑这全都归结为在逐元素比较期间是否引发异常,请参见。 herehere

如果包含数组的两个对应元素是数组本身并且具有兼容的形状(如A==A1),则它们的比较将生成一个布尔数组。试图将其转换为标量布尔值会引发异常。当前,会捕获异常并返回标量False。

A==At示例中,比较最后两个元素时会引发异常,因为它们的形状不会广播。将捕获此错误,并且对此元素的比较返回标量False,这就是为什么包含数组的比较返回“正常”布尔数组的原因。

@ kmario23和@Kanak建议的解决方法如何?他们工作吗?

好吧,是的...

>>> np.equal(A, A1, dtype=object)
array([True, array([ True,  True,  True])], dtype=object)
>>> wrpr(np.equal(A, A1, dtype=object))
True

...不。

>>> AA = np.array([None, A])
>>> AA1 = np.array([None, A1])
>>> np.equal(AA, AA1, dtype=object)
array([True, False], dtype=object)
>>> wrpr(np.equal(AA, AA1, dtype=object))
False

答案 2 :(得分:1)

为补充@ kmario23的答案,该怎么做

def wrpr(bools):
    ints  = np.prod(bools.flatten())
    if isinstance(ints, np.ndarray):
        return wrpr(ints)
    return bool(ints)

最后

>>> wrpr(np.equal(ce, be, dtype=np.object))
True

使用(numpy1.15.1&Python 3.6.5)和(numpy1.15.1&Python 2.7.13)检查


但是仍然如此,如here

所评论
  

NumPy用于刚性的多维数字网格。试图获得除了刚性多维网格之外的任何东西都将是痛苦的。 (@ user2357112,17年7月31日在23:10)

和/或

  

故事的寓意:不要使用dtype=object数组。它们是性能低下的Python列表,性能很差,并且numpy并非旨在处理这些对象数组中类似序列的容器的情况。   (@ juanpa.arrivillaga,17年7月31日在23:38)