【问题标题】:Is there a Matlab's buffer equivalent in numpy?numpy中是否有Matlab的缓冲区等价物?
【发布时间】:2016-07-19 08:30:37
【问题描述】:

我看到有一个 array_splitsplit methods 但是当您必须拆分一个长度不是块大小整数倍的数组时,这些并不是很方便。而且,这些方法输入的是切片数量而不是切片大小。我需要更像 Matlab 的 buffer 方法,它更适合信号处理。

例如,如果我想将信号缓冲到大小为 60 的块中,我需要这样做:np.vstack(np.hsplit(x.iloc[0:((len(x)//60)*60)], len(x)//60)),这很麻烦。

【问题讨论】:

  • 你试过np.split吗?它在指定的索引处拆分,因此应注意不规则的间隔。我们只需要使用范围创建这些索引。
  • 快速浏览buffer 文档让我想起了numpy stride_tricks.as_strided,尤其是它处理重叠和跳过的能力。但对于这种情况,这可能太强大了,也太危险了。
  • x.reshape(-1,60) 会将x 分成大小相等的 60 行。如果x 的长度不是 60 的倍数,则必须填充或截断。但是vstack 也需要这样做。

标签: python matlab numpy buffer


【解决方案1】:

我编写了以下例程来处理我需要的用例,但我还没有实现/测试“underlap”。

请随时提出改进建议。

def buffer(X, n, p=0, opt=None):
    '''Mimic MATLAB routine to generate buffer array

    MATLAB docs here: https://se.mathworks.com/help/signal/ref/buffer.html

    Parameters
    ----------
    x: ndarray
        Signal array
    n: int
        Number of data segments
    p: int
        Number of values to overlap
    opt: str
        Initial condition options. default sets the first `p` values to zero,
        while 'nodelay' begins filling the buffer immediately.

    Returns
    -------
    result : (n,n) ndarray
        Buffer array created from X
    '''
    import numpy as np

    if opt not in [None, 'nodelay']:
        raise ValueError('{} not implemented'.format(opt))

    i = 0
    first_iter = True
    while i < len(X):
        if first_iter:
            if opt == 'nodelay':
                # No zeros at array start
                result = X[:n]
                i = n
            else:
                # Start with `p` zeros
                result = np.hstack([np.zeros(p), X[:n-p]])
                i = n-p
            # Make 2D array and pivot
            result = np.expand_dims(result, axis=0).T
            first_iter = False
            continue

        # Create next column, add `p` results from last col if given
        col = X[i:i+(n-p)]
        if p != 0:
            col = np.hstack([result[:,-1][-p:], col])
        i += n-p

        # Append zeros if last row and not length `n`
        if len(col) < n:
            col = np.hstack([col, np.zeros(n-len(col))])

        # Combine result with next row
        result = np.hstack([result, np.expand_dims(col, axis=0).T])

    return result

【讨论】:

  • 为我工作了一个小调整。因为我使用的是 Python 3(我的理论),所以“cols”变量被截断了。认为这是由于 Python 3 处理乘法的方式发生了变化。我将分母转换为在计算“cols”的方程中浮动,然后输出与我的情况完全匹配 Matlab 的输出。 cols = int(np.ceil(len(x)/float((n-p))))
  • 谢谢。我也在使用 Python 3,但我最终没有使用它,所以也许我只是没有注意到。
  • 你可以试试下面的测试用例。它给出了错误的输出。 data = buffer(np.arange(1,31),7,3,'nodelay')
  • 我已经查看并更正了您提到的@Maxtron 错误。谢谢!
  • 只是一个小评论。当同时选择 p=0nodelay 选项时,算法会抛出错误。测试用例:data = buffer(np.arange(1,31),7,0,'nodelay')
【解决方案2】:
def buffer(X = np.array([]), n = 1, p = 0):
    #buffers data vector X into length n column vectors with overlap p
    #excess data at the end of X is discarded
    n = int(n) #length of each data vector
    p = int(p) #overlap of data vectors, 0 <= p < n-1
    L = len(X) #length of data to be buffered
    m = int(np.floor((L-n)/(n-p)) + 1) #number of sample vectors (no padding)
    data = np.zeros([n,m]) #initialize data matrix
    for startIndex,column in zip(range(0,L-n,n-p),range(0,m)):
        data[:,column] = X[startIndex:startIndex + n] #fill in by column
    return data

【讨论】:

    【解决方案3】:

    与其他答案相同,但速度更快。

    def buffer(X, n, p=0):
    
        '''
        Parameters
        ----------
        x: ndarray
            Signal array
        n: int
            Number of data segments
        p: int
            Number of values to overlap
    
        Returns
        -------
        result : (n,m) ndarray
            Buffer array created from X
        '''
        import numpy as np
    
        d = n - p
        m = len(X)//d
    
        if m * d != len(X):
            m = m + 1
    
        Xn = np.zeros(d*m)
        Xn[:len(X)] = X
    
        Xn = np.reshape(Xn,(m,d))
        Xne = np.concatenate((Xn,np.zeros((1,d))))
        Xn = np.concatenate((Xn,Xne[1:,0:p]), axis = 1)
    
        return np.transpose(Xn[:-1])
    

    【讨论】:

      【解决方案4】:

      ryanjdillon 的答案重写以显着提高性能;它附加到一个列表而不是连接数组,后者迭代地复制数组并且速度要慢得多。

      def buffer(x, n, p=0, opt=None):
          if opt not in ('nodelay', None):
              raise ValueError('{} not implemented'.format(opt))
      
          i = 0
          if opt == 'nodelay':
              # No zeros at array start
              result = x[:n]
              i = n
          else:
              # Start with `p` zeros
              result = np.hstack([np.zeros(p), x[:n-p]])
              i = n-p
          # Make 2D array, cast to list for .append()
          result = list(np.expand_dims(result, axis=0))
      
          while i < len(x):
              # Create next column, add `p` results from last col if given
              col = x[i:i+(n-p)]
              if p != 0:
                  col = np.hstack([result[-1][-p:], col])
      
              # Append zeros if last row and not length `n`
              if len(col):
                  col = np.hstack([col, np.zeros(n - len(col))])
      
              # Combine result with next row
              result.append(np.array(col))
              i += (n - p)
      
          return np.vstack(result).T
      

      【讨论】:

        【解决方案5】:
        def buffer(X, n, p=0):
        '''
        Parameters:
        x: ndarray, Signal array, input a long vector as raw speech wav
        n: int, frame length
        p: int, Number of values to overlap
        -----------
        Returns:
        result : (n,m) ndarray, Buffer array created from X
        '''
        import numpy as np
        d = n - p
        #print(d)
        m = len(X)//d
        c = n//d
        #print(c)
        if m * d != len(X):
            m = m + 1
        #print(m)
        
        Xn = np.zeros(d*m)
        Xn[:len(X)] = X
        Xn = np.reshape(Xn,(m,d))
        Xn_out = Xn
        for i in range(c-1):
            Xne = np.concatenate((Xn,np.zeros((i+1,d))))
            Xn_out = np.concatenate((Xn_out, Xne[i+1:,:]),axis=1)
        #print(Xn_out.shape)  
        if n-d*c>0:
            Xne = np.concatenate((Xn, np.zeros((c,d))))
            Xn_out = np.concatenate((Xn_out,Xne[c:,:n-p*c]),axis=1)
        
        return np.transpose(Xn_out)
        

        这里是 Ali Khodabakhsh 的示例代码的改进代码,在我的情况下不起作用。随意评论和使用它。

        【讨论】:

          【解决方案6】:

          通过运行比较建议答案的执行时间

          x = np.arange(1,200000)
          start = timer()
          y = buffer(x,60,20)
          end = timer()
          print(end-start)
          

          结果是:

          安德烈·梅,0.005595300000095449

          霸王金龙,0.06954789999986133

          ryanjdillon,2.427092700000003

          【讨论】:

            【解决方案7】:

            这个 Keras 函数可以被认为是 MATLAB Buffer() 的 Python 等价物。

            查看示例代码:

            import numpy as np
            S = np.arange(1,99) #A Demo Array
            

            See Output Here

            import tensorflow.keras.preprocessing as kp
            list(kp.timeseries_dataset_from_array(S, targets = None,sequence_length=7,sequence_stride=7,batch_size=5))
            

            See the Buffered Array Output Here

            参考:See This

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2021-12-08
              • 2016-03-27
              • 2019-12-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-07-22
              相关资源
              最近更新 更多