如何在 numpy 数组的元素之间插入零?

问题描述 投票:0回答:6

我有一个 nd 数组,例如这个:

x = np.array([[1,2,3],[4,5,6]])

我想将最后一个维度的大小加倍,并在元素之间插入零以填充空间。结果应该如下所示:

[[1,0,2,0,3,0],[4,0,5,0,6,0]]

我尝试使用

expand_dims
pad
来解决它。但是
pad
函数不仅在最后一个维度的每个值之后插入零。结果的形状是
(3, 4, 2)
,但应该是
(2,3,2)

y = np.expand_dims(x,-1)
z = np.pad(y, (0,1), 'constant', constant_values=0)
res = np.reshape(z,[-1,2*3]

我的代码的结果:

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

如何使用

pad
在每个元素后面的最后一个维度中插入零?或者有什么更好的方法可以解决这个问题吗?

python arrays numpy
6个回答
19
投票

只需初始化输出数组并使用

slicing
-

进行分配
m,n = x.shape
out = np.zeros((m,2*n),dtype=x.dtype)
out[:,::2] = x

或者堆叠 -

np.dstack((x,np.zeros_like(x))).reshape(x.shape[0],-1)

10
投票

您可以使用insert功能来完成:

np.insert(arr=x, obj=[1,2,3], values=0, axis=1)

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

其中

obj
是插入值的索引 before


2
投票

对我发现的一些方法进行了基准测试:
(1) 分指标赋值
(2) 跨步技巧
(3) 填充
(4) 连接

def dilation1(X, d):
    Xd_shape = np.multiply(X.shape, d)
    Xd = np.zeros(Xd_shape, dtype=X.dtype)
    Xd[0:Xd_shape[0]:d[0], 0:Xd_shape[1]:d[1]] = X
    return Xd

def dilation2(X, d):
    Xd_shape = np.multiply(X.shape, d)
    Xd = np.zeros(Xd_shape, dtype=X.dtype)
    Xdn = np.lib.stride_tricks.as_strided(Xd, X.shape, np.multiply(Xd.strides, d))
    Xdn[:] = X
    return Xd

def dilation3(X, d):
    Xd = X.reshape((X.shape[0],1,X.shape[1],1))
    Xd = np.pad(Xd, ((0,0),(0,d[0]-1),(0,0),(0,d[1]-1)))
    return Xd.reshape(np.multiply(X.shape,d))

def dilation4(X, d):
    Xd = X.reshape((X.shape[0],1,X.shape[1],1))
    mcol = np.zeros(Xd.shape[:3]+(d[1]-1,))
    Xd = np.concatenate((Xd, mcol), 3)
    mrow = np.zeros((Xd.shape[0],d[0]-1)+Xd.shape[2:])
    Xd = np.concatenate((Xd, mrow), 1)
    return Xd.reshape(np.multiply(X.shape,d))

#Example
b = np.arange(3*3).reshape((3,3))
b
# array([[0, 1, 2],
#        [3, 4, 5],
#        [6, 7, 8]])
dilation1(b, (3,2))
# array([[0, 0, 1, 0, 2, 0],
#        [0, 0, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0],
#        [3, 0, 4, 0, 5, 0],
#        [0, 0, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0],
#        [6, 0, 7, 0, 8, 0],
#        [0, 0, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0]])

#Benchmark
a = np.random.randn(1024,1024)

%timeit -r 20 dilation1(a, (5,5))
#19.7 ms ± 890 µs per loop (mean ± std. dev. of 20 runs, 100 loops each)

%timeit -r 20 dilation2(a, (5,5))
#18.8 ms ± 526 µs per loop (mean ± std. dev. of 20 runs, 100 loops each)

%timeit -r 20 dilation3(a, (5,5))
#101 ms ± 2.32 ms per loop (mean ± std. dev. of 20 runs, 10 loops each)

%timeit -r 20 dilation4(a, (5,5))
#101 ms ± 1.59 ms per loop (mean ± std. dev. of 20 runs, 10 loops each)

所以只需使用子索引赋值即可。


1
投票

沿着你的expand_dims,我们可以使用

stack

In [742]: x=np.arange(1,7).reshape(2,-1)
In [743]: x
Out[743]: 
array([[1, 2, 3],
       [4, 5, 6]])
In [744]: np.stack([x,x*0],axis=-1).reshape(2,-1)
Out[744]: 
array([[1, 0, 2, 0, 3, 0],
       [4, 0, 5, 0, 6, 0]])

stack
使用
expend_dims
添加维度;它就像
np.array
但可以更好地控制如何添加新轴。因此,这是一种散布数组的便捷方法。

堆栈产生一个 (2,4,2) 数组,我们将其重塑为 (2,8)。

x*0
可以替换为
np.zeros_like(x)
,或任何创建相同大小的零数组的东西。

np.stack([x,x*0],axis=1).reshape(4,-1)
添加 0 行。


0
投票

您只需填充新尺寸的一侧

x = np.array( [[1,2,3],[4,5,6]] ) y = np.expand_dims(x,-1) z = np.pad( y, ((0, 0), (0, 0), (0, 1)) , 'constant', constant_values=0) res = np.reshape(z, ( x.shape[0] , 2*x.shape[1] ) ) res

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

    

0
投票
您可以使用

scipy.signal.upfirdn

 来完成此操作:

>>> import numpy as np >>> from scipy.signal import upfirdn >>> x = np.array([[1, 2, 3], [4, 5, 6]]) >>> upfirdn([1], x, 2) array([[1., 0., 2., 0., 3.], [4., 0., 5., 0., 6.]]) >>> upfirdn([1], x, 3) array([[1., 0., 0., 2., 0., 0., 3.], [4., 0., 0., 5., 0., 0., 6.]])
第一个参数是 FIR 滤波器系数,使用 

[1]

 将使值保持不变。第三个参数是零的数量-1。

© www.soinside.com 2019 - 2024. All rights reserved.