当前位置: 首页 > 知识库问答 >
问题:

比较dtype对象的numpy数组

杨凯旋
2023-03-14

我的问题是"为什么?:"

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中。

我没有在aa中使用aaa,因为DeprecationWarning:elementwise==比较失败;这将在将来引发一个错误。,因为如果有人想知道,它仍然返回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]))

当然还有其他问题告诉我这应该行得通。。。


共有3个答案

段干祺
2023-03-14

你看到的行为在这里有记录

反对意见(

...

对象数组相等性比较

在将来的对象数组比较中,==和np.equal将不再使用标识检查。例如:

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

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

a==b

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

如果广播或元素比较失败,相等运算符==将在将来引发错误,如np.equal等。

与arr==None的比较将在将来执行元素级比较,而不是仅返回False。代码应使用arr is None。

所有这些更改都会在此时发出弃用或未来警告。

到目前为止,一切都很清楚。还是这样?

我们可以从@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])
>>> 

看起来现在的行为更多的是巧合,而不是精心策划的结果。

我怀疑这一切都归结于是否在元素级比较期间引发了异常,参见这里和这里。

如果包含数组的两个相应元素本身是数组,并且具有兼容的形状,如A==A1,则它们的比较会产生一个布尔数组。试图将此转换为标量bool会引发异常。目前,异常被捕获并返回标量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
孟浩慨
2023-03-14

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

def wrpr(bools):
    try:
      # ints  = bools.flatten().prod()
        fltn_bools = np.hstack(bools)
    except: # should not pass silently.
        fltn_bools = np.array(wrpr(a) for a in bools)        
    ints = fltn_bools.prod()
    if isinstance(ints, np.ndarray):
        return wrpr(ints)
    return bool(ints)

最后,

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

检查使用

但是,正如这里所评论的

NumPy是为刚性多维数字网格设计的。除了一个僵硬的多维网格之外,想要得到任何东西都是痛苦的。(@user23571122017年7月31日23:10)

和/或

故事的寓意:不要使用dtype=对象数组。它们是发育不良的Python列表,具有更差的性能特性,而Numpy不是设计来处理这些对象数组中类似序列的容器的情况。(@juanpa.arrivillaga,Jul 31'17 at 23:38)

贺亦
2023-03-14

要在数组之间进行元素级比较,可以使用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)

使用NumPy版本1.15.2和Python3.6.6

从1.15的发行说明中,

https://docs.scipy.org/doc/numpy-1.15.1/release.html#comparison-ufuncs接受覆盖默认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).
 类似资料:
  • 如果两个集合包含相同的对象,如何进行比较? 当然会打印错误。

  • 是否有一种惯用的方法来比较两个NumPy数组,它们将NaN视为彼此相等(但不等于NaN以外的任何东西)。 例如,我希望以下两个数组比较相等: 和以下两个数组进行比较: 我正在寻找一种可以产生标量布尔结果的方法。 以下方法可以做到这一点: 但它很笨重,并且创建了所有这些中间数组。 有没有一种方法可以更容易地观察眼睛,更好地利用记忆? 另外,如果有帮助的话,已知数组具有相同的形状和数据类型。

  • 问题内容: 我想比较JavaScript代码中2个对象数组。这些对象共有8个属性,但是每个对象都不会有一个值,并且每个数组的大小永远都不能超过8个,因此可能要使用遍历每个对象然后查看对象的值的蛮力方法。 8个属性是执行我想做的最简单的方法,但是在实现之前,我想看看是否有人有一个更优雅的解决方案。有什么想法吗? 问题答案: 编辑:您不能在JavaScript解释器的当前基于浏览器的常见实现中重载运算

  • 假设我有一个叫“序列”的类。这个类有一个实例变量。还有一些方法可以创建这个选项卡,比如: 现在,我想创建一个方法,它接受两个Sequence对象作为参数,并返回相同tab元素的数量。所以,我创建了这样的方法:

  • 问题内容: 对于我的单元测试,我想检查两个数组是否相同。简化示例: 这是行不通的,因为。最好的进行方法是什么? 问题答案: 或者您可以使用或用: 编辑 由于您正在使用它进行单元测试,因此裸露(而不是将其包装成get )可能更自然。

  • 问题内容: 我得到的错误就在这行 。 该怎么办?其他逻辑还可以吗? 我想做的是有一个A列表和一个B列表,其中一个属性与id相同;尽管变量名不同。即在和在B。现在我将两个列表都放在ListAll中,并在相同的变量id / bid上对它们进行排序。我有A和B实现可比性。 和我的listAll是对象类型? 我该怎么做?谢谢。 问题答案: 您可以添加一个通用基类并在那里进行比较,如下所示: