Python:相同形状数组

时间:2015-08-07 22:03:52

标签: 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(单元格2,1和2,3匹配所有3个矩阵)或[[False,False,False],[True,False,True]数组, [假,假,假]]?

3 个答案:

答案 0 :(得分:4)

使用np.dstack沿第三轴连接,并使用np.diff进行分支,以便相同的那些显示为零。然后,检查所有都为~np.any的零的情况。因此,您将拥有像这样的单线解决方案 -

~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)

答案 1 :(得分:3)

你可以这样做:

(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参数的axis函数是理想的,但没有一个,所以这一行注意到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))那么修改上述函数defs适当地并且添加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.的列表,如果输入数组很大,那么快速接近大约4倍就是单独存储它们在列表中。我发现这有点令人惊讶,并猜测这可能是由于缓存交换(或错误的代码?),但我不确定是否有人真正关心所以我会在这里停止它。

答案 2 :(得分:1)

试试这个:

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) )