【问题标题】:matrix: move n-th row by n position efficiently矩阵:有效地将第 n 行移动 n 个位置
【发布时间】:2019-11-04 13:14:21
【问题描述】:

我有一个 numpy 2d 数组,我需要将其转换为第一行保持不变,第二行向右移动一个位置,(它可以环绕或仅在前面填充零) .第三行向右移动 3 个位置,依此类推。 我可以通过“for循环”来做到这一点,但这不是很有效。我猜应该有一个与原始矩阵相乘的过滤矩阵会产生相同的效果,或者可能是一个可以帮助我做到这一点的 numpy 技巧?谢谢! 我已经研究过 numpy.roll() 但我认为它不能单独在每一行上工作。

import numpy as np
p = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]])
'''
p = [ 1   2   3   4
      5   6   7   8
      9   10  11  12
      13  14  15  16]
desired output:
p'= [ 1   2   3   4
      0   5   6   7
      0   0   9   10
      0   0   0   13]
'''

【问题讨论】:

    标签: python numpy matrix matrix-transform


    【解决方案1】:

    我们可以将滑动窗口提取到输入的零填充版本中,以获得内存高效的方法,因此也可以提高性能。要获得这些窗口,我们可以利用基于scikit-image's view_as_windowsnp.lib.stride_tricks.as_stridedMore info on use of as_strided based view_as_windows.

    因此,解决方案是 -

    from skimage.util.shape import view_as_windows
    
    def slide_by_one(p):
        m,n = p.shape
        z = np.zeros((m,m-1),dtype=p.dtype)
        a = np.concatenate((z,p),axis=1)
        w  = view_as_windows(a,(1,p.shape[1]))[...,0,:]
        r = np.arange(m)
        return w[r,r[::-1]]
    

    示例运行 -

    In [60]: p # generic sample of size mxn
    Out[60]: 
    array([[ 1,  5,  9, 13, 17],
           [ 2,  6, 10, 14, 18],
           [ 3,  7, 11, 15, 19],
           [ 4,  8, 12, 16, 20]])
    
    In [61]: slide_by_one(p)
    Out[61]: 
    array([[ 1,  5,  9, 13, 17],
           [ 0,  2,  6, 10, 14],
           [ 0,  0,  3,  7, 11],
           [ 0,  0,  0,  4,  8]])
    

    我们可以利用常规的 rampy 模式来获得更有效的方法,更原始地使用np.lib.stride_tricks.as_strided,就像这样 -

    def slide_by_one_v2(p):
        m,n = p.shape
        z = np.zeros((m,m-1),dtype=p.dtype)
        a = np.concatenate((z,p),axis=1)
        s0,s1 = a.strides
        return np.lib.stride_tricks.as_strided(a[:,m-1:],shape=(m,n),strides=(s0-s1,s1))
    

    另一个有一些masking -

    def slide_by_one_v3(p):
        m,n = p.shape
        z = np.zeros((len(p),1),dtype=p.dtype)
        a = np.concatenate((p,z),axis=1)
        return np.triu(a[:,::-1],1)[:,::-1].flat[:-m].reshape(m,-1)
    

    【讨论】:

      【解决方案2】:

      这是一个基于零填充和重塑的简单方法。它速度很快,因为它避免了高级索引和其他开销。

      def pp(p):
          m,n = p.shape
          aux = np.zeros((m,n+m-1),p.dtype)
          np.copyto(aux[:,:n],p)
          return aux.ravel()[:-m].reshape(m,n+m-2)[:,:n].copy()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-03-25
        • 1970-01-01
        • 1970-01-01
        • 2016-03-14
        • 1970-01-01
        • 2019-06-18
        • 1970-01-01
        相关资源
        最近更新 更多