组合两个不同维度的numpy数组

时间:2017-12-02 00:41:57

标签: python numpy

当我阅读numpy教程时,我给自己挑战以建立我的理解。当我在上一个例子中看到他们的最终产品修改后的数组不是真正的数组时,我正在阅读tutorialpoint.com的numpy资源。

页面底部,广播迭代示例: https://www.tutorialspoint.com/numpy/numpy_iterating_over_array.htm

所以我认为尝试创建与数组相同的最终产品将是一个很好的挑战。我成功了,但是我无法使用np.nditer,也无法利用广播,虽然我确信必须有一种方法可以利用这两种方式。

这是我的代码:

a = np.arange(0,60,5) 
a = a.reshape(12,1)
b = np.arange(1,5)
arr = np.zeros((12,2))

counter = 0
for i in range(arr.shape[0]):
    if counter < 4:
        arr[i,:] = np.array([a[i],b[counter]])
        counter += 1
    else:
        counter = 0
        arr[i,:] = np.array([a[i],b[counter]])

print arr

如何更有效地完成这项工作?

1 个答案:

答案 0 :(得分:0)

之前我还没有看过那个特别的nditer教程 https://docs.scipy.org/doc/numpy-1.13.0/reference/arrays.nditer.html

是我使用的那个。我一直告诉人们nditer,使用这个Python界面,效率不高。此页面最适合作为在C代码中使用nditer的垫脚石,如上一个cython示例所示。

没有很多numpy函数使用np.nditer(在Python代码中)。 np.ndindex是为数不多的之一。值得一读的是它的代码。 np.einsum使用此迭代器,但在编译代码中。

我稍后会花时间阅读并评论相关示例。学习使用广播比使用nditer更重要。

In [212]: a=np.arange(0,60,5).reshape(3,4)
In [213]: a
Out[213]: 
array([[ 0,  5, 10, 15],
       [20, 25, 30, 35],
       [40, 45, 50, 55]])
In [214]: b=np.arange(1,5)
In [215]: b
Out[215]: array([1, 2, 3, 4])

In [225]: for x,y in np.nditer([a,b]):
     ...:     print("%d:%d"%(x,y), end=' ')
     ...: print()
0:1 5:2 10:3 15:4 20:1 25:2 30:3 35:4 40:1 45:2 50:3 55:4 

等效纯Python迭代:

In [231]: for row in a:
     ...:     for x,y in zip(row,b):
     ...:         print("%d:%d"%(x,y), end=' ')
     ...: print()
     ...: 
0:1 5:2 10:3 15:4 20:1 25:2 30:3 35:4 40:1 45:2 50:3 55:4 

np.broadcast将使用(4,):

广播(3,4)数组
In [234]: np.broadcast(a,b)
Out[234]: <numpy.broadcast at 0x9c2a7f8>
In [235]: list(_)
Out[235]: 
[(0, 1),
 (5, 2),
 (10, 3),
 (15, 4),
 (20, 1),
 (25, 2),
 (30, 3),
 (35, 4),
 (40, 1),
 (45, 2),
 (50, 3),
 (55, 4)]

使用np.array(list(np.broadcast(a,b)))创建一个(12,2)数组。

或者使用相同的印刷品:

In [237]: for x,y in np.broadcast(a,b):
     ...:     print("%d:%d"%(x,y), end=' ')
     ...: print()
     ...: 
0:1 5:2 10:3 15:4 20:1 25:2 30:3 35:4 40:1 45:2 50:3 55:4

你的迭代:

In [251]: arr = np.zeros((12,2),dtype=int)
     ...: counter = 0
     ...: for i in range(arr.shape[0]):
     ...:     if counter < 4:
     ...:         arr[i,:] = np.array([a.flat[i],b[counter]])
     ...:         counter += 1
     ...:     else:
     ...:         counter = 0
     ...:         arr[i,:] = np.array([a.flat[i],b[counter]])
     ...:         
In [252]: arr
Out[252]: 
array([[ 0,  1],
       [ 5,  2],
       [10,  3],
       [15,  4],
       [20,  1],
       [25,  1],
       [30,  2],
       [35,  3],
       [40,  4],
       [45,  1],
       [50,  1],
       [55,  2]])

糟糕,如果您希望第二列重复b,则看起来像是关闭的。

ab组合到这种数组中有很多方法。

这将2d a变为1d;使用b复制tile,并将其与stack联合起来(column_stack也会有效):

In [264]: np.stack((a.flat, np.tile(b,3)),1)
Out[264]: 
array([[ 0,  1],
       [ 5,  2],
       [10,  3],
       [15,  4],
       [20,  1],
       [25,  2],
       [30,  3],
       [35,  4],
       [40,  1],
       [45,  2],
       [50,  3],
       [55,  4]])