Python 滚动窗口或2D矩阵的引用(以每行Numpy为单位)?

Python 滚动窗口或2D矩阵的引用(以每行Numpy为单位)?,python,numpy,matrix,window,find-occurrences,Python,Numpy,Matrix,Window,Find Occurrences,在寻找矩阵每一行上出现的模式时,我发现在python上没有明确的解决方案,因为非常大的矩阵具有良好的性能 我有一个类似于的矩阵 matrix = np.array([[0,1,1,0,1,0], [0,1,1,0,1,0]]) print 'matrix: ', matrix 我想检查每一行上[0,0]、[0,1][1,0]和[1,1]模式的发生率。对于给定的示例,如果两行相等,则每个模式的结果相等: 模式[0,0]=[0,0] 模式[0,1

在寻找矩阵每一行上出现的模式时,我发现在python上没有明确的解决方案,因为非常大的矩阵具有良好的性能

我有一个类似于的矩阵

matrix = np.array([[0,1,1,0,1,0],
                         [0,1,1,0,1,0]])
print 'matrix: ', matrix
我想检查每一行上[0,0]、[0,1][1,0]和[1,1]模式的发生率。对于给定的示例,如果两行相等,则每个模式的结果相等:

  • 模式[0,0]=[0,0]
  • 模式[0,1]=[2,2]
  • 模式[1,0]=[2,2]
  • 模式[1,1]=[1,1]
本例中的矩阵非常小,但我正在寻找性能,因为我有一个巨大的矩阵。例如,您可以使用
matrix=numpy.random.randint(2,size=(100000,10))
或更大的值来测试矩阵,以查看差异

首先,我考虑了一个可能的答案,将行转换为字符串,并根据()查找出现的情况:

使用答案的功能
出现次数

def occurrences(string, sub):
    count = start = 0
    while True:
        start = string.find(sub, start) + 1
        if start > 0:
            count+=1
        else:
            return count
但是考虑到实际数组是巨大的,这个解决方案非常慢,因为它用于循环、字符串,。。。 因此,为了寻找numpy解决方案,我使用了一个技巧,将值与模式进行比较,并在轴=1上滚动矩阵,以检查所有出现的情况。 我称之为二维上的伪滚动窗口,因为窗口不是正方形的,计算方式不同。有两个选项,其中第二个(选项2)更快,因为它避免了额外计算
numpy.roll

def pseudo_rolling_window_Opt12(matrix):
    print '\n===== pseudo_rolling_window ====='
    numRow,numCol = np.shape(matrix)
    Ocur = np.zeros((numRow,4))
    index = 0
    for i in np.arange(2):
        for j in np.arange(2):
            #pattern = -9*np.ones(numCol)   # Option 1
            pattern = -9*np.ones(numCol+1)  # Option 2
            pattern[0] = i
            pattern[1] = j
            for idCol in range(numCol-1):
                #Ocur[:,index] += np.sum(np.roll(matrix,-idCol, axis=1) == pattern, axis=1) == 2    # Option 1: 219.398691893 seconds (for my real matrix)
                Ocur[:,index] += np.sum(matrix[:,idCol:] == pattern[:-(idCol+1)], axis=1) == 2      # Option 2:  80.929688930 seconds (for my real matrix)
            index += 1
    return Ocur
在寻找其他可能性时,我发现了“滚动窗口”,它似乎是性能的最佳答案,因为它使用了numpy函数。查看()及其链接,我检查了以下函数。但实际上,我不理解输出,因为窗口的计算似乎与我预期的结果相符

def rolling_window(a, size):
    shape = a.shape[:-1] + (a.shape[-1] - size + 1, size)
    strides = a.strides + (a.strides[-1],)
    return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)
用作:

a = rolling_window(matrix, 2)
print a == np.array([0,1])
print np.all(rolling_window(matrix, 2) == [0,1], axis=1)

有人知道最后一个案子出了什么问题吗?或者性能更好的可能性是什么?

您使用了错误的numpy阵列轴。您应该将np.all中的轴从1更改为2。 使用以下代码:

a = rolling_window(matrix, 2)
print np.all(rolling_window(matrix, 2) == [0,1], axis=2)
你会得到:

>>>[[ True False False  True False]
    [ True False False  True False]]
因此,为了获得您想要的结果:

print np.sum(np.all(rolling_window(matrix, 2) == [0,1], axis=2),axis=1)

>>>[2 2]

完全正确。。。在查找输出的numpy形状(x,y,z)之后,我没有意识到axis被设置为1。谢谢你。为了满足其他用户的好奇心,rolling_window选项将我使用的伪滚动窗口的执行时间减少了50%,是获得良好性能的完美选择!!!
print np.sum(np.all(rolling_window(matrix, 2) == [0,1], axis=2),axis=1)

>>>[2 2]