矢量化numpy数组扩展

时间:2015-07-30 12:35:36

标签: python arrays numpy vectorization

我试图找到一种方法来矢量化一个操作,我采用1个numpy数组并将每个元素扩展为4个新点。我目前正在使用Python循环。首先让我解释一下算法。

input_array = numpy.array([1, 2, 3, 4])

我想扩大'或者'延伸'这个数组中的每个元素为4个点。因此,元素零(值1)将扩展到这4个点:

[0, 1, 1, 0]

每个元素都会发生这种情况,最终得到一个最终数组:

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

我想使代码略显通用,这样我才能执行此扩展'以不同的方式。例如:

input_array = numpy.array([1, 2, 3, 4])

这次通过向每个点添加+ = .2来扩展每个点。所以,最后一个数组将是:

[.8, .8, 1.2, 1.2, 1.8, 1.8, 2.2, 2.2, 2.8, 2.8, 3.2, 3.2, 3.8, 3.8, 4.2, 4.2]

我目前使用的代码如下所示。这是一个非常天真的方法,但似乎有办法加快大型阵列的速度:

output = []
for x in input_array:
    output.append(expandPoint(x))

output = numpy.concatenate(output)

def expandPoint(x):
    return numpy.array([0, x, x, 0])

def expandPointAlternativeStyle(x):
    return numpy.array([x - .2, x - .2, x + .2, x + .2])

4 个答案:

答案 0 :(得分:2)

对于第一个示例,您可以使用np.kron

>>> a = np.array([0, 1, 1, 0])
>>> np.kron(input_array, a)
array([0, 1, 1, 0, 0, 2, 2, 0, 0, 3, 3, 0, 0, 4, 4, 0])

对于第二个示例,您可以使用np.repeatnp.tile

>>> b = np.array([-0.2, -0.2, 0.2, 0.2])
>>> np.repeat(input_array, b.size) + np.tile(b, input_array.size)
array([ 0.8,  0.8,  1.2,  1.2,  1.8,  1.8,  2.2,  2.2,  2.8,  2.8,  3.2,
        3.2,  3.8,  3.8,  4.2,  4.2])

答案 1 :(得分:2)

我不确定你算法的逻辑,但我认为如果你希望每个点都围绕它extend,然后将它们排在一起,那么你最好的方法就是增加维度,然后采取扁平版;第一个例子:

>>> x = np.array([1,2,3,4])
>>> x
array([1, 2, 3, 4])
>>> y = np.empty((len(x), 4))
>>> y[:, [0, 3]] = 0
>>> y[:, 1:3] = x[:, None]
>>> y
array([[ 0.,  1.,  1.,  0.],
       [ 0.,  2.,  2.,  0.],
       [ 0.,  3.,  3.,  0.],
       [ 0.,  4.,  4.,  0.]])
>>> y.reshape((4*len(x),))  # Flatten it back
array([ 0.,  1.,  1.,  0.,  0.,  2.,  2.,  0.,  0.,  3.,  3.,  0.,  0.,
    4.,  4.,  0.])

然后你如何制作这种泛型取决于你的算法,我并不完全肯定会遵循这个算法......但这应该会给你一些启动的指示。

编辑:正如其他人所说,你可以用更简洁的方式实现外部产品的所有这些,这可能会更紧密地匹配你的算法,例如,羞耻地让YXD回答一个-liner:

>>> (x[:, None] * np.array([0,1,1,0])[None, :]).flatten()
array([0, 1, 1, 0, 0, 2, 2, 0, 0, 3, 3, 0, 0, 4, 4, 0])

然而,在原始维度(1)扩展之前,原则仍然是更高维度(2)

答案 2 :(得分:1)

对于第一个示例,您可以执行输入和模板的外部产品并重新整形结果:

input_array = np.array([1, 2, 3, 4])
template = np.array([0, 1, 1, 0])

np.multiply.outer(input_array, template)
# array([[0, 1, 1, 0],
#        [0, 2, 2, 0],
#        [0, 3, 3, 0],
#        [0, 4, 4, 0]])

result = np.multiply.outer(input_array, template).ravel()
# array([0, 1, 1, 0, 0, 2, 2, 0, 0, 3, 3, 0, 0, 4, 4, 0])

与第二个示例类似,您可以使用np.add.outer

np.add.outer(input_array, [-0.2, -0.2, 0.2, 0.2]).ravel()
# array([ 0.8,  0.8,  1.2,  1.2,  1.8,  1.8,  2.2,  2.2,  2.8,  2.8,  3.2,
        3.2,  3.8,  3.8,  4.2,  4.2])

请参阅:

答案 3 :(得分:1)

您似乎希望在input_array和包含扩展元素的数组之间进行元素运算。对于这些,您可以使用broadcasting

对于第一个示例,您似乎正在执行elementwise multiplication -

In [424]: input_array = np.array([1, 2, 3, 4])
     ...: extend_array = np.array([0, 1, 1, 0])
     ...: 

In [425]: (input_array[:,None] * extend_array).ravel()
Out[425]: array([0, 1, 1, 0, 0, 2, 2, 0, 0, 3, 3, 0, 0, 4, 4, 0])

对于第二个示例,您似乎正在执行elementwise addition -

In [422]: input_array = np.array([1, 2, 3, 4])
     ...: extend_array = np.array([-0.2, -0.2, 0.2, 0.2])
     ...: 

In [423]: (input_array[:,None] + extend_array).ravel()
Out[423]: 
array([ 0.8,  0.8,  1.2,  1.2,  1.8,  1.8,  2.2,  2.2,  2.8,  2.8,  3.2,
        3.2,  3.8,  3.8,  4.2,  4.2])