计算在另一个数组中没有重叠的数组的出现次数

时间:2017-02-15 14:59:39

标签: python performance numpy

我有一个mxn矩阵A,其中m%t = n%t = 0,以便较小的txt矩阵B平铺矩阵,没有边框或重叠。我想检查A是否完全由B中的切片组成,而不是尽可能有效地计算切片作为中间步骤。此外,对于我的特殊用例,没有必要知道B。只需测试A是否在每个方向上严格重复每个txt磁贴。

数字示例:

A = [[1, 0, 1, 0],
     [0, 1, 0, 1],
     [1, 0, 1, 0],
     [0, 1, 0, 1]]
B.shape = [2,2]
--> True
B.shape = [1,1]
--> False

到目前为止,我计算了一个比较矩阵C,它只是B的平铺,以适合A的大小:

import numpy as np
x,y      = B.shape
x_a, y_a = A.shape
x_t = x_a/x
y_t = y_a/y
B_dash = A[:x, :y]
C = np.tile(B_dash,(x_t, y_t))
np.count_nonzero(A-C)

有没有更快的方法,而不计算C

2 个答案:

答案 0 :(得分:3)

Appproach#1:我们似乎正在计算A中B的出现次数为不同的块。所以,我们可以使用skimage.util.view_as_blocks -

from skimage.util import view_as_blocks as viewW

out = np.count_nonzero((viewW(A, B.shape) == B).all((2,3)))

Appproach#2:坚持NumPy,我们会 -

m1,n1 = A.shape
m2,n2 = B.shape
out = np.count_nonzero((A.reshape(m1//m2,m2,n1//n2,n2) == B[:,None]).all((1,3)))

样品运行 -

In [274]: A
Out[274]: 
array([[2, 0, 2, 0],
       [5, 3, 5, 1],
       [3, 3, 2, 6],
       [1, 0, 3, 1]])

In [275]: B
Out[275]: 
array([[3, 3],
       [1, 0]])

In [276]: np.count_nonzero((viewW(A, B.shape) == B).all((2,3)))
Out[276]: 1



In [278]: A
Out[278]: 
array([[2, 0, 3, 3],
       [5, 3, 1, 0],
       [3, 3, 2, 6],
       [1, 0, 3, 1]])

In [279]: B
Out[279]: 
array([[3, 3],
       [1, 0]])

In [280]: np.count_nonzero((viewW(A, B.shape) == B).all((2,3)))
Out[280]: 2

答案 1 :(得分:0)

可以在不生成C的情况下获得结果。您可以通过以下方式获得结果:

x,y      = B.shape
x_a, y_a = A.shape
np.array_equal(A[:, :y_a-y], A[:, y:]) and np.array_equal(A[:x_a-x, :], A[x:, :])

也就是说,要比较A的第一个y_a-y列及其最后y_a-y列,然后对行执行类似的操作。我还没有测试上面的代码,但它应该更快,因为使用此方法numpy将不会分配新内存。

最后一个语句可以优化为:

np.array_equal(A[:, :y_a-y], A[:, y:]) and np.array_equal(A[:x_a-x, :y_a], A[x:, :y_a])

因为如果第一个词是True,我们已经知道A列重复了t次。