Python:相同形状数组的元素级比较

Python:相同形状数组的元素级比较,python,numpy,Python,Numpy,我有n个大小相同的矩阵,我想看看所有矩阵中有多少个单元彼此相等。代码: import numpy as np a = np.array([[1,2,3],[4,5,6],[7,8,9]]) b = np.array([[5,6,7], [4,2,6], [7, 8, 9]]) c = np.array([2,3,4],[4,5,6],[1,2,5]) #Intuition is below but is wrong a == b == c 如何让Python返回2的值(所有3个矩阵中的单元格

我有n个大小相同的矩阵,我想看看所有矩阵中有多少个单元彼此相等。代码:

import numpy as np
a = np.array([[1,2,3],[4,5,6],[7,8,9]])
b = np.array([[5,6,7], [4,2,6], [7, 8, 9]])
c = np.array([2,3,4],[4,5,6],[1,2,5])

#Intuition is below but is wrong
a == b == c
如何让Python返回2的值(所有3个矩阵中的单元格2,1和2,3都匹配)或[[False,False,False]、[True,False,True]、[False,False]]的数组?

您可以执行以下操作:

(a == b) & (b==c)

[[False False False]
 [ True False  True]
 [False False False]]
对于
n
项,例如,类似
x=[a,b,c,a,b,c]
的列表,可以执行以下操作:

r = x[0] == x[1]
for temp in x[2:]:
    r &= x[0]==temp
结果现在显示在
r

如果结构已在3D numpy阵列中,还可以使用:

np.amax(x,axis=2)==np.amin(x,axis=2)
上面这一行的想法是,虽然理想的做法是使用带有
参数的
equal
函数,但没有这样的函数,因此这一行注意到,如果
amin==amax
沿着轴,那么所有元素都是相等的


如果要比较的不同阵列尚未在3D numpy阵列中(或将来不会),则循环列表是一种快速而简单的方法。虽然我通常同意避免为Numpy数组使用Python循环,但在这种情况下,使用Python循环似乎更容易、更快(见下文),因为循环只沿着一个轴,并且比较容易累积到位。下面是一个计时测试:

def f0(x):
    r = x[0] == x[1]
    for y in x[2:]:
        r &= x[0]==y

def f1(x):  # from @Divakar
    r = ~np.any(np.diff(np.dstack(x),axis=2),axis=2)

def f2(x):
    x = np.dstack(x)
    r = np.amax(x,axis=2)==np.amin(x,axis=2)

# speed test
for n, size, reps in ((1000, 3, 1000), (10, 1000, 100)):
    x = [np.ones((size, size)) for i in range(n)]
    print n, size, reps
    print "f0: ",
    print timeit("f0(x)", "from __main__ import x, f0, f1", number=reps)
    print "f1: ",
    print timeit("f1(x)", "from __main__ import x, f0, f1", number=reps)
    print

1000 3 1000
f0:  1.14673900604  # loop
f1:  3.93413209915  # diff
f2:  3.93126702309  # min max

10 1000 100
f0:  2.42633581161  # loop
f1:  27.1066679955  # diff
f2:  25.9518558979  # min max
如果阵列已经在单个3D numpy阵列中(例如,在上面使用
x=np.dstack(x)
),则适当修改上述函数def,并添加
min==max
方法,可得出:

def g0(x):
    r = x[:,:,0] == x[:,:,1]
    for iy in range(x[:,:,2:].shape[2]):
        r &= x[:,:,0]==x[:,:,iy]

def g1(x):   # from @Divakar
    r = ~np.any(np.diff(x,axis=2),axis=2)

def g2(x):
    r = np.amax(x,axis=2)==np.amin(x,axis=2)
这将产生:

1000 3 1000
g0:  3.9761030674      # loop
g1:  0.0599548816681   # diff
g2:  0.0313589572906   # min max

10 1000 100
g0:  10.7617051601     # loop
g1:  10.881870985      # diff
g2:  9.66712999344     # min max
还要注意的是,对于大型数组的列表,f0=2.4和预构建数组,g0、g1、g2~=10.,因此,如果输入数组很大,则最快的方法是将它们分别存储在一个列表中。我觉得这有点奇怪,并猜测这可能是由于缓存交换(或错误的代码?),但我不确定是否有人真的在乎,因此我将在这里停止此操作。

尝试以下方法:

z1 = a == b
z2 = a == c
z  = np.logical_and(z1,z2)
print "count:", np.sum(z)
您可以在一条语句中执行此操作:

count = np.sum( np.logical_and(a == b, a == c) )

沿第三个轴连接和执行微分,以便相同的显示为零。然后,检查所有为零的情况。因此,您将有一个这样的一行解决方案-

~np.any(np.diff(np.dstack((a,b,c)),axis=2),axis=2)
样本运行-

In [39]: a
Out[39]: 
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])

In [40]: b
Out[40]: 
array([[5, 6, 7],
       [4, 2, 6],
       [7, 8, 9]])

In [41]: c
Out[41]: 
array([[2, 3, 4],
       [4, 5, 6],
       [1, 2, 5]])

In [42]: ~np.any(np.diff(np.dstack((a,b,c)),axis=2),axis=2)
Out[42]: 
array([[False, False, False],
       [ True, False,  True],
       [False, False, False]], dtype=bool)

有一个普遍的答案吗?如果我有3个以上的矩阵,那么得出答案所需的组合和步骤将爆炸。@user1842834:我还应该注意,“组合”不会爆炸。没有组合和爆炸,这只是O(n)。将其视为一个单元素数组,例如数字
5
。然后你有一个数字列表,然后你沿着列表询问每个元素是否等于
5
。这只是一个矩阵。没有必要对每个元素进行比较。