简体   繁体   English

向量化numpy数组扩展

[英]Vectorize numpy array expansion

I'm trying to find a way to vectorize an operation where I take 1 numpy array and expand each element into 4 new points. 我试图找到一种向量化操作的方法,其中我采用1个numpy数组并将每个元素扩展为4个新点。 I'm currently doing it with Python loop. 我目前正在使用Python循环进行此操作。 First let me explain the algorithm. 首先让我解释一下算法。

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

I want to 'expand' or 'extend' each element in this array to 4 points. 我想将该数组中的每个元素“扩展”或“扩展”到4点。 So, element zero (value 1) would be expanded to these 4 points: 因此,元素零(值1)将扩展为以下4点:

[0, 1, 1, 0]

This would happen for each element to end up with a final array of: 对于每个元素,最终的最终数组都是这样:

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

I'd like to make the code slightly generic so that I could also perform this 'expansion' in a different way. 我想使代码稍微通用一些,以便我也可以以其他方式执行此“扩展”。 For example: 例如:

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

This time each point is expanded by adding += .2 to each point. 这次,通过在每个点上添加+ = 0.2来扩展每个点。 So, the final array would be: 因此,最终的数组将是:

[.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]

The code I'm currently using looks like this. 我当前正在使用的代码如下所示。 It's a pretty naive approach that works but seems like there would be a way to speed it up for large arrays: 这是一种非常幼稚的方法,但是似乎有一种方法可以加快大型阵列的运行速度:

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])

For the first example, you can use np.kron 对于第一个示例,可以使用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])

For the second example, you can use np.repeat and np.tile 对于第二个示例,可以使用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])

I'm not certain of the logic of your algorithm, but I think if you want each point to extend around it, and then queue them all together, your best approach would be to increase the dimension, and then take the flattened version; 我不确定算法的逻辑,但是我认为如果希望每个点都围绕它extend ,然后将它们全部排队,则最好的方法是增大尺寸,然后采用扁平化的版本。 for your first example: 对于第一个示例:

>>> 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.])

How you then go about making that generic depends on your algorithm, which I'm not entirely sure to follow... But this should give you some pointers to get started. 然后如何制作该泛型取决于您的算法,我不确定要完全遵循该算法。但这应该为您提供一些入门指南。

Edit : As others have stated, you can actually do all that with outer products in a much more concise way, which will probably match your algorithm more closely, eg, shamelessely making YXD answer a one-liner: 编辑 :正如其他人所说,实际上您可以以更简洁的方式对外部产品进行所有操作,这可能与您的算法更紧密地匹配,例如,羞耻地使YXD回答单一问题:

>>> (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])

However, the principle is still to go in a higher dimension (2) before expanding it in you original dimension (1) 但是,原理是在将其扩展到原始尺寸(1)之前,它仍应沿较高的尺寸(2)前进。

For the first example, you can do an outer product of the input and the template and reshape the result: 对于第一个示例,您可以对输入和模板进行外积运算并调整结果的形状:

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])

Similarly for your second example you can use np.add.outer 同样,对于第二个示例,您可以使用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])

See: 看到:

It seems you want to want to do elementwise operations between input_array and the array that contains the extending elements. 似乎您想在input_array和包含扩展元素的数组之间进行input_array元素的操作。 For these, you can use broadcasting . 对于这些,您可以使用broadcasting

For the first example, it seems you are performing elementwise multiplication - 对于第一个示例,似乎您正在执行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])

For the second example, it seems you are performing elementwise addition - 对于第二个示例,似乎您正在执行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])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM