比较两个NumPy数组的相等性,按元素


251

比较两个NumPy数组是否相等的最简单方法是什么(其中相等定义为:对于所有索引i:,A = B iff A[i] == B[i])?

简单地使用==给我一个布尔数组:

 >>> numpy.array([1,1,1]) == numpy.array([1,1,1])

array([ True,  True,  True], dtype=bool)

是否and需要确定该数组的元素是否相等,或者是否有更简单的比较方法?

Answers:


377
(A==B).all()

测试数组(A == B)的所有值是否均为True。

注意:也许您还想测试A和B形状,例如 A.shape == B.shape

特殊情况和替代方法(来自dbaupp的回答和yoavram的评论)

应当指出的是:

  • 在特定情况下,此解决方案可能会产生奇怪的行为:如果AB为空且另一个包含单个元素,则返回True。由于某种原因,比较会A==B返回一个空数组,all操作员将为此返回一个空数组True
  • 另一个风险是,如果AB形状不相同且不可广播,则此方法将引发错误。

总之,如果你有一个关于怀疑AB形状或只是想安全:的专业功能用途之一:

np.array_equal(A,B)  # test if same shape, same elements values
np.array_equiv(A,B)  # test if broadcastable shape, same elements values
np.allclose(A,B,...) # test if same shape, elements have close enough values

25
您几乎总是需要np.array_equalIME。如果A和B的长度不同,(A==B).all()将会崩溃。从numpy 1.10开始,在这种情况下==会引发弃用警告
Wilfred Hughes

您的观点很不错,但在这种情况下,我对形状还是有疑问,通常我会更喜欢在值之前直接对其进行测试。那么,误差显然是在形状上具有完全不同的含义而在形状上具有不同的值。但这可能取决于每个用例
Juh_

2
另一个风险是如果数组包含nan。在这种情况下,您会得到False,因为nan!= nan
Vincenzooo

1
指出这一点很高兴。但是,我认为这是合乎逻辑的,因为它nan!=nan暗示了array(nan)!=array(nan)
Juh_

我不了解这种行为: import numpy as np H = 1/np.sqrt(2)*np.array([[1, 1], [1, -1]]) #hadamard matrix np.array_equal(H.dot(H.T.conj()), np.eye(len(H))) # checking if H is an unitary matrix or not H是一个unit矩阵,因此H x H.T.conj是一个单位矩阵。但是np.array_equal返回False
Dex,

90

(A==B).all()解决方案是很整齐,但也有完成这个任务的一些内置的功能。也就是说array_equalallclosearray_equiv

(尽管,使用进行一些快速测试timeit似乎表明该(A==B).all()方法是最快的,由于必须分配一个全新的数组,因此该方法有点特殊。)


15
您是对的,除了如果比较的数组之一为空,您将得到错误的答案(A==B).all()。例如,尝试:(np.array([1])==np.array([])).all(),它给了True,而np.array_equal(np.array([1]), np.array([]))False
yoavram

1
我也刚刚发现了这种性能差异。这很奇怪,因为如果您拥有2个完全不同的数组,其(a==b).all()速度仍然比np.array_equal(a, b)(可能只检查了一个元素并退出)要快。
艾丹·凯恩2015年

np.array_equal也可用于lists of arraysdicts of arrays。这可能是性能降低的原因。
2016年

非常感谢该函数allclose,这是我进行数值计算所需要的。它比较容差内向量的相等。:)
耶稣的爱。18/ 09/25

注意np.array_equiv([1,1,1], 1) is True。这是因为:形状一致意味着它们要么是相同的形状,要么可以广播一个输入数组以创建与另一个形状相同的形状。
EliadL

13

让我们通过使用以下代码来评估性能。

import numpy as np
import time

exec_time0 = []
exec_time1 = []
exec_time2 = []

sizeOfArray = 5000
numOfIterations = 200

for i in xrange(numOfIterations):

    A = np.random.randint(0,255,(sizeOfArray,sizeOfArray))
    B = np.random.randint(0,255,(sizeOfArray,sizeOfArray))

    a = time.clock() 
    res = (A==B).all()
    b = time.clock()
    exec_time0.append( b - a )

    a = time.clock() 
    res = np.array_equal(A,B)
    b = time.clock()
    exec_time1.append( b - a )

    a = time.clock() 
    res = np.array_equiv(A,B)
    b = time.clock()
    exec_time2.append( b - a )

print 'Method: (A==B).all(),       ', np.mean(exec_time0)
print 'Method: np.array_equal(A,B),', np.mean(exec_time1)
print 'Method: np.array_equiv(A,B),', np.mean(exec_time2)

输出量

Method: (A==B).all(),        0.03031857
Method: np.array_equal(A,B), 0.030025185
Method: np.array_equiv(A,B), 0.030141515

根据上面的结果,numpy方法似乎比==运算符和all()方法的组合要快,并且通过比较numpy方法,最快的方法似乎是numpy.array_equal方法。


4
您应该使用较大的阵列大小,至少要花一秒钟的时间进行编译,以提高实验精度。
Vikhyat Agarwal

当比较顺序更改时,这还会重现吗?还是每次都要随机初始化A和B?也可以从A和B单元的内存缓存中解释这种差异。
或格罗曼

3
这些时间之间没有有意义的区别。
To마SE

13

如果要检查两个数组是否相同shape并且elements应该使用,np.array_equal因为这是文档中建议的方法。

在性能方面,不要期望任何相等性检查会胜过另一个,因为没有太多的优化空间comparing two elements。为了方便起见,我仍然进行了一些测试。

import numpy as np
import timeit

A = np.zeros((300, 300, 3))
B = np.zeros((300, 300, 3))
C = np.ones((300, 300, 3))

timeit.timeit(stmt='(A==B).all()', setup='from __main__ import A, B', number=10**5)
timeit.timeit(stmt='np.array_equal(A, B)', setup='from __main__ import A, B, np', number=10**5)
timeit.timeit(stmt='np.array_equiv(A, B)', setup='from __main__ import A, B, np', number=10**5)
> 51.5094
> 52.555
> 52.761

几乎相等,无需谈论速度。

(A==B).all()的行为几乎如下面的代码片段:

x = [1,2,3]
y = [1,2,3]
print all([x[i]==y[i] for i in range(len(x))])
> True

5

通常两个数组会有一些小的数字误差,

您可以使用numpy.allclose(A,B)代替(A==B).all()。这将返回布尔值True / False


0

现在使用np.array_equal。从文档:

np.array_equal([1, 2], [1, 2])
True
np.array_equal(np.array([1, 2]), np.array([1, 2]))
True
np.array_equal([1, 2], [1, 2, 3])
False
np.array_equal([1, 2], [1, 4])
False
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.