【问题标题】:Slicing 2D numpy array periodically定期切片 2D numpy 数组
【发布时间】:2021-12-21 08:53:06
【问题描述】:

我有一个 300x300 的 numpy 数组,我想在其中定期保留所有元素。具体来说,对于两个轴,我想保留前 5 个元素,然后丢弃 15、保留 5、丢弃 15 等。这将产生一个 75x75 元素的数组。如何做到这一点?

【问题讨论】:

    标签: python arrays numpy slice


    【解决方案1】:

    另一个使用网格和模数的选项:

    # MyArray = 300x300 numpy array
    r      = np.r_[0:300]              # A slide from 0->300
    xv, yv = np.meshgrid(r, r)         # x and y grid
    mask   = ((xv%20)<5) & ((yv%20)<5) # We create the boolean mask
    result = MyArray[mask].reshape((75,75)) # We apply the mask and reshape the final output
    

    【讨论】:

      【解决方案2】:

      这是我第一个想到的解决方案。如果我想到行数较少的,稍后会更新。即使输入不是正方形,这也应该有效:

      output = []
      for i in range(len(arr)):
          tmp = []
          if i % (15+5) < 5:         # keep first 5, then discard next 15
              for j in range(len(arr[i])):
                  if j % (15+5) < 5: # keep first 5, then discard next 15
                      tmp.append(arr[i,j])
              output.append(tmp)
      

      更新:

      以杨的回答为基础,这是使用np.tile 的另一种方式,它沿每个轴重复一个数组给定的次数。这依赖于输入数组的维度是正方形。

      import numpy as np
      
      # Define one instance of the keep/discard box
      keep, discard = 5, 15
      mask = np.concatenate([np.ones(keep), np.zeros(discard)])
      mask_2d = mask.reshape((keep+discard,1)) * mask.reshape((1,keep+discard))
      
      # Tile it out -- overshoot, then trim to match size
      count = len(arr)//len(mask_2d) + 1
      tiled = np.tile(mask_2d, [count,count]).astype('bool')
      tiled = tiled[:len(arr), :len(arr)]
      
      # Apply the mask to the input array
      dim = sum(tiled[0])
      output = arr[tiled].reshape((dim,dim))
      

      【讨论】:

        【解决方案3】:

        您可以将数组视为一系列 20x20 块,您希望保留其中左上角 5x5 的部分。假设你有

        keep = 5
        discard = 15
        

        这仅在以下情况下有效

        assert all(s % (keep + discard) == 0 for s in arr.shape)
        

        首先计算视图的形状并使用它:

        block = keep + discard
        shape1 = (arr.shape[0] // block, block, arr.shape[1] // block, block)
        view = arr.reshape(shape1)[:, :keep, :, :keep]
        

        以下操作将创建数据的副本,因为视图创建了一个不连续的缓冲区:

        shape2 = (shape1[0] * keep, shape1[2] * keep)
        result = view.reshape(shape2)
        

        您可以使用更通用的方式计算 shape1shape2,例如

        shape1 = tuple(
            np.stack((np.array(arr.shape) // block,
                      np.full(arr.ndim, block)), -1).ravel())
        shape2 = tuple(np.array(shape1[::2]) * keep)
        

        我建议将其打包成一个函数。

        【讨论】:

          【解决方案4】:

          您可以创建一个执行保留/丢弃功能的一维蒙版,然后重复蒙版并将蒙版应用于数组。这是一个例子。

          import numpy as np
          
          size = 300
          array = np.arange(size).reshape((size, 1)) * np.arange(size).reshape((1, size))
          
          mask = np.concatenate((np.ones(5), np.zeros(15))).astype(bool)
          period = len(mask)
          
          mask = np.repeat(mask.reshape((1, period)), repeats=size // period, axis=0)
          mask = np.concatenate(mask, axis=0)
          
          result = array[mask][:, mask]
          
          print(result.shape)
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-01-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-11-19
            相关资源
            最近更新 更多