我有一个像
这样的二维数组small = np.arange(9).reshape((3, 3))
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
我想应用填充,每行填充左侧的变量0。并确保结果2d数组的形状为3 x 8.(右侧填充0)
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
答案 0 :(得分:4)
方法#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
的scikit-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]
答案 1 :(得分:0)
PaddedMat=numpy.zeros(shape=[3,8],dtype="float")
然后循环填充它。
PaddedMat[i,offset[i]:offset[i]+3]=small[i,:]
等...