簡體   English   中英

定期切片 2D numpy 數組

[英]Slicing 2D numpy array periodically

我有一個 300x300 的 numpy 數組,我想定期保留所有元素。 具體來說,對於兩個軸,我想保留前 5 個元素,然后丟棄 15 個、保留 5 個、丟棄 15 個等。這應該會產生一個 75x75 元素的數組。 如何才能做到這一點?

您可以創建一個執行保留/丟棄功能的一維蒙版,然后重復蒙版並將蒙版應用到數組。 這是一個例子。

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)

這是我第一個想到的解決方案。 如果我想到行數較少的將稍后更新。 即使輸入不是方形的,這也應該有效:

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)

更新:

根據 Yang 的回答,這是另一種使用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))

您可以將數組視為一系列 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)

我建議將其打包成一個函數。

使用 meshgrid 和模數的另一種選擇:

# 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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM