没有对齐的元素Efficent插入一个numpy的阵列 [英] Efficent insertion of not aligned elements in a numpy array

查看:109
本文介绍了没有对齐的元素Efficent插入一个numpy的阵列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用numpy的 1.9 在一组阵列的工作。假设我有类似的东西,我有两个二维数组 A B 和一维数组<$ C $ ç> C ,这看起来像:

 &GT;&GT;&GT;一个
阵列([1,1,1,1,1]
       [1,1,1,1,1]
       [1,1,1,1,1]
       [1,1,1,1,1]
       [1.,1。,1.,1.,1。]])
&GT;&GT;&GT;乙
阵列([[ - 。。1,-1,-1,-1,-1],
       [-1,-1,-1,-1,-1],
       [-1,-1,-1,-1,-1],
       [-1,-1,-1,-1,-1],
       [-1,-1,-1,-1,-1]])
&GT;&GT;&GT; C
阵列([1,3,2,4,0])

我的目标是从B A的所有元素插入,按C.更具体地讲,如果C位置0有一个1,B [0,1]应该是[0,1]。

下面是预期的结果是:

 阵列([1,1,-1,1,1,1],
       [1,1,1,1,-1,1],
       [1,1,1,-1,1,1],
       [1,1,1,1,1,-1],
       [1,-1,1,1,1,1]])

我想实现它这样的,但它不是非常快:

 对我的xrange(尺寸(C,0)):
    J = C [I]
    A [我:] = numpy.insert(A [I],J,B [I,J])

有一种方法,使其更快? (跟单操作numpy的做到这一点,像面具或类似的东西)


解决方案

如何讨厌单行?

首先,数据;该阵列具有相同的形状是你的,但我已经用整数使例子更易于阅读。

 在[81]:一
出[81]:
阵列([0,1,2,3,4],
       [5,6,7,8,9],
       [10,11,12,13,14],
       [15,16,17,18,19],
       [20,21,22,23,24])在[82]:乙
出[82]:
阵列([0,100,200,300,400],
       [500,600,700,800,900],
       [1000,1100,1200,1300,1400],
       [1500,1600,1700,1800,1900]
       [2000,2100,2200,2300,2400])在[83]:C
出[83]:阵列([1,3,2,4,0])

而这里的肮脏一行代码:

 在[84]:np.insert(A.ravel(),np.ravel_multi_index((范围(A.shape [0]),C),A.shape)+ 1,B [范围(B.shape [0]),C])。重塑(A.shape [0],A.shape [1] +1)
出[84]:
阵列([0,1,100,2,3,4],
       [5,6,7,8,800 9]
       [10,11,12,1200,13,14],
       [15,16,17,18,19,1900]
       [20,2000,21,22,23,24])

这里是破旧的版本:

A.ravel()平坦 A 成一维数组,我会打电话给˚F

 在[87]:F = A.ravel()在[88]:F
出[88]:
阵列([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,
       17,18,19,20,21,22,23,24])

(编辑:原来这第一步 - 展平 A - 是不是必要的,因为在@hpaulj他的回答中指出,。 np.insert 将平由默认的阵列。)

np.ravel_multi_index 用于所期望的2-D位置到索引转换成扁平阵列。在 + 1 末,因为要插入的元素的是必要的后的在 C中列出该指数

 在[89]:insert_indices = np.ravel_multi_index((范围(A.shape [0]),C),A.shape)+ 1在[90]:insert_indices
出[90]:阵列([2,9,13,20,21])

B [范围(B.shape [0]),C] 拉所需的值了 B的

 在[91]:值= B [范围(B.shape [0]),C]在[92]:值
出[92]:阵列([100,800,1200,1900,2000)

np.insert 执行实际插入并创建一个新的数组:

 在[93]:np.insert(F,insert_indices,价值观)
出[93]:
阵列([0,1,100,2,3,4,5,6,7,8,800,
          9,10,11,12,1200,13,14,15,16,17,18,
         19,1900,20,2000,21,22,23,24])

现在只是重塑,要得到最终的结果是:

 在[94]:np.insert(F,insert_indices,价值观).reshape(A.shape [0],A.shape [1] +1)
出[94]:
阵列([0,1,100,2,3,4],
       [5,6,7,8,800 9]
       [10,11,12,1200,13,14],
       [15,16,17,18,19,1900]
       [20,2000,21,22,23,24])

I'm using numpy 1.9 to work on a set of arrays. Assuming I have something like that I have two 2d arrays A and B and a 1-d array C, that looks like that:

>>> A
array([[ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.]])
>>> B
array([[-1., -1., -1., -1., -1.],
       [-1., -1., -1., -1., -1.],
       [-1., -1., -1., -1., -1.],
       [-1., -1., -1., -1., -1.],
       [-1., -1., -1., -1., -1.]])
>>> C
array([1, 3, 2, 4, 0])

My goal is to insert in A all elements from B, according to C. More specifically, if C at position 0 has a 1, B[0, 1] should be inserted after A[0, 1].

Here's the expected result:

array([[ 1,  1, -1,  1,  1,  1],
       [ 1,  1,  1,  1, -1,  1],
       [ 1,  1,  1, -1,  1,  1],
       [ 1,  1,  1,  1,  1, -1],
       [ 1, -1,  1,  1,  1,  1]])

I tried to implement it like that, but it's not very fast:

for i in xrange(size(C, 0)):
    j = C[i]
    A[i, :] = numpy.insert(A[i], j, B[i, j])

There is a way to make it faster? (do it with a single numpy operation, like masks or something like that)

解决方案

How about a nasty one-liner?

First, the data; the arrays have the same shape as yours, but I've used integers to make the example easier to read.

In [81]: A
Out[81]: 
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19],
       [20, 21, 22, 23, 24]])

In [82]: B
Out[82]: 
array([[   0,  100,  200,  300,  400],
       [ 500,  600,  700,  800,  900],
       [1000, 1100, 1200, 1300, 1400],
       [1500, 1600, 1700, 1800, 1900],
       [2000, 2100, 2200, 2300, 2400]])

In [83]: C
Out[83]: array([1, 3, 2, 4, 0])

And here's the nasty one-liner:

In [84]: np.insert(A.ravel(), np.ravel_multi_index((range(A.shape[0]), C), A.shape) + 1, B[range(B.shape[0]), C]).reshape(A.shape[0], A.shape[1]+1)
Out[84]: 
array([[   0,    1,  100,    2,    3,    4],
       [   5,    6,    7,    8,  800,    9],
       [  10,   11,   12, 1200,   13,   14],
       [  15,   16,   17,   18,   19, 1900],
       [  20, 2000,   21,   22,   23,   24]])

Here's the broken-down version:

A.ravel() flattens A into a 1-d array, which I'll call F:

In [87]: F = A.ravel()

In [88]: F
Out[88]: 
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
       17, 18, 19, 20, 21, 22, 23, 24])

(EDIT: It turns out this first step--flattening A--is not necessary. As @hpaulj points out in his answer, np.insert will flatten the array by default.)

np.ravel_multi_index is used to convert the desired 2-d positions into the indices into the flattened array. The + 1 at the end is necessary because you want to insert the elements after the index given in C:

In [89]: insert_indices = np.ravel_multi_index((range(A.shape[0]), C), A.shape) + 1

In [90]: insert_indices
Out[90]: array([ 2,  9, 13, 20, 21])

B[range(B.shape[0]), C] pulls the desired values out of B:

In [91]: values = B[range(B.shape[0]), C]

In [92]: values
Out[92]: array([ 100,  800, 1200, 1900, 2000])

np.insert does the actual insertion and creates a new array:

In [93]: np.insert(F, insert_indices, values)
Out[93]: 
array([   0,    1,  100,    2,    3,    4,    5,    6,    7,    8,  800,
          9,   10,   11,   12, 1200,   13,   14,   15,   16,   17,   18,
         19, 1900,   20, 2000,   21,   22,   23,   24])

Now just reshape that to get the final result:

In [94]: np.insert(F, insert_indices, values).reshape(A.shape[0], A.shape[1]+1)
Out[94]: 
array([[   0,    1,  100,    2,    3,    4],
       [   5,    6,    7,    8,  800,    9],
       [  10,   11,   12, 1200,   13,   14],
       [  15,   16,   17,   18,   19, 1900],
       [  20, 2000,   21,   22,   23,   24]])

这篇关于没有对齐的元素Efficent插入一个numpy的阵列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆