簡體   English   中英

如何填充左右行每行長度可變的2d數組以形成更大的2d數組

[英]How to pad a 2d array with variable length per row on the left and right to form a bigger 2d array

我有一個二維數組

small = np.arange(9).reshape((3, 3))

array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])

我想應用填充,每一行填充左側的變量0。 並確保結果2d數組的形狀為3 x8。(右側填充0s)

offset = np.array([1, 3, 2])

這樣結果看起來像

array([[ 0.,  0.,  1.,  2.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  3.,  4.,  5.,  0.,  0.],
       [ 0.,  0.,  6.,  7.,  8.,  0.,  0.,  0.]])

實現此目標的最佳方法是什么?

感謝@Divakar解決方案。 我對以下方法進行了一些基准測試。

def f1(small, offset, ncols):
    nrows, num_small_cols = small.shape
    big = np.zeros((nrows, ncols))
    inner = np.empty_like(small, dtype=np.int64)
    for i in range(num_small_cols):
        inner[:, i] = offset + i
    big[np.arange(nrows)[:, None], inner] = small
    return big

def f2(small, offset, ncols):
    n = small.shape[1]
    r = np.arange(ncols)
    offset2 = offset[:,None]
    # This took a lot of time
    mask = (offset2 <= r) & (offset2 + n > r)
    out = np.zeros_like(mask, dtype=np.float64)
    out[mask] = small.ravel()
    return out

def f3(small, offset, ncols):
    n = small.shape[1]
    m = ncols - n
    small_pad = np.zeros((len(small), n + 2*m))
    small_pad[:,m:m+n] = small    
    w = view_as_windows(small_pad, (1,ncols))[:,:,0]
    return w[np.arange(len(offset)), ncols-offset-n]

n = 10000
offset = np.repeat(np.array([1, 3, 2]), n)
small = np.random.rand(n * 3, 5)

%timeit f1(small, offset, 9)
# 1.32 ms

%timeit f2(small, offset, 9)
# 2.24 ms

%timeit f3(small, offset, 9)
# 1.3 ms

方法1

我們可以使用broadcasting來創建一個掩碼,以分配給這些位置,然后分配給以零開頭的數組-

def pad_offsetpos(small, ncols):
    n = small.shape[1]
    r = np.arange(ncols)
    mask = (offset[:,None] <= r) & (offset[:,None]+n > r)
    out = np.zeros(mask.shape)
    out[mask] = small.ravel()
    return out

樣品運行-

In [327]: small
Out[327]: 
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])

In [328]: offset
Out[328]: array([1, 3, 2])

In [329]: pad_offsetpos(small, ncols=8)
Out[329]: 
array([[0., 0., 1., 2., 0., 0., 0., 0.],
       [0., 0., 0., 3., 4., 5., 0., 0.],
       [0., 0., 6., 7., 8., 0., 0., 0.]])

方法#2

我們還可以np.lib.stride_tricks.as_strided基於np.lib.stride_tricks.as_stridedscikit-image's view_as_windows進行有效的補丁提取之后,在輸入數組的兩邊都填充足夠的零-

from skimage.util.shape import view_as_windows

def pad_offsetpos_strided(small, ncols):
    n = small.shape[1]
    m = ncols - n
    small_pad = np.zeros((len(small), n + 2*m))
    small_pad[:,m:m+n] = small    
    w = view_as_windows(small_pad, (1,ncols))[:,:,0]
    return w[np.arange(len(offset)), ncols-offset-n]
PaddedMat=numpy.zeros(shape=[3,8],dtype="float")

然后循環填充它。

PaddedMat[i,offset[i]:offset[i]+3]=small[i,:]

等等...

暫無
暫無

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

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