关于初始化ndarray的“如何”问题

时间:2019-08-10 16:52:51

标签: python numpy

很抱歉,这个问题是否已经得到回答(我找不到任何相关的信息),但是如何在不使用循环或对值进行硬编码的情况下初始化3维数组?

我想创建一个3维的。形状为(x,y,2)的数组,并对其进行初始化,以使第三轴中的值表示前两个轴的索引。例如,[[[0,0],[0,1],[0,2]],[[1,0],[1,1],[1,2]]]。我不想使用循环来做到这一点(尽管这样做非常简单),因为实际尺寸会很大(对于图像处理应用程序而言),并且我想避免使用循环。

这是显而易见的方式:

arr = np.empty((600,800,2))
for row in range(600):
    for col in range(800):
        arr[row,col] = [row,col]

是否有一种更有效的,类似numpy的方法?

4 个答案:

答案 0 :(得分:2)

Numpy具有np.indices((行,列))

np.indices((800, 600)).shape
# (2, 800, 600)

res= np.indices((800, 600)).swapaxes(0,2).swapaxes(0,1)
res.shape
# (800, 600, 2)

%timeit np.indices((800, 600)).swapaxes(0,2).swapaxes(0,1)
# 6.77 ms ± 41.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit try3(800, 600)
# 24 ms ± 702 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

或者使用np.moveaxis。我的时间与双交换轴的时间相同。

np.moveaxis( np.indices((800, 600)), 0, 2)

希望这会有所帮助

答案 1 :(得分:1)

您的代码产生(在较小的情况下):

In [208]: arr = np.empty((3,4,2)) 
     ...: for row in range(3): 
     ...:     for col in range(4): 
     ...:         arr[row,col] = [row,col] 
     ...:                                                                                                    
In [209]: arr                                                                                                
Out[209]: 
array([[[0., 0.],
        [0., 1.],
        [0., 2.],
        [0., 3.]],

       [[1., 0.],
        [1., 1.],
        [1., 2.],
        [1., 3.]],

       [[2., 0.],
        [2., 1.],
        [2., 2.],
        [2., 3.]]])
In [221]: arr.shape                                                                                          
Out[221]: (3, 4, 2)

mgrid是制作网格的几种功能之一,它产生:

In [222]: np.mgrid[0:3,0:4]                                                                                  
Out[222]: 
array([[[0, 0, 0, 0],
        [1, 1, 1, 1],
        [2, 2, 2, 2]],

       [[0, 1, 2, 3],
        [0, 1, 2, 3],
        [0, 1, 2, 3]]])
In [223]: _.shape                                                                                            
Out[223]: (2, 3, 4)

我们可以通过转置得到arr

In [224]: np.mgrid[0:3,0:4].transpose(1,2,0).shape                                                           
Out[224]: (3, 4, 2)

np.meshgrid产生相似的结果,但作为数组的元组。

还可以使用repeattile上的np.arange(3)np.arange(4)的混合。

np.reshape(list(np.ndindex(3,4)),(3,4,2)) 
np.reshape(list(itertools.product(range(3),range(4))),(3,4,2)) 

也可以使用,尽管它的速度可能与您的代码相似。 `

答案 2 :(得分:0)

当涉及到numpy时,请尽可能避免迭代。这里一种可能的方法是,您可以使用arange来构造一个一维数组,其中包含所有您需要预先准备的数字,然后使用一些numpy操纵来获得所需的输出。

import numpy as np       
x = 600
y = 800
def try1(x, y):
    arr = np.empty((x,y,2))
    for row in range(x):
        for col in range(y):
            arr[row,col] = [row,col]
    return arr

def try2(x, y):
    temp = np.arange(x * y)
    outer = temp // y
    inner = temp % y
    out = np.dstack((outer, inner)).reshape(x, y, 2)
    return out

%timeit try1(x, y)
#489 ms ± 2.22 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit try2(x, y)
#10.6 ms ± 98.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

编辑:

我还添加了hpaulj的mgrid答案,这显然更好:

def try3(x, y):
    return np.mgrid[0:x,0:y].transpose(1,2,0)

%timeit try3(x, y)
#8.39 ms ± 43.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

答案 3 :(得分:0)

我想我可以使用以下代码实现您想要的:

import numpy as np

arr = np.empty((600,800,2))
first_indices = np.repeat(np.arange(600).reshape(600, 1), 800, axis=1)
arr[:,:,0] = first_indices
second_indices = np.repeat(np.arange(800).reshape(800,1), 600, axis=1).T
arr[:,:,1] = second_indices
print(arr)

这有点简洁,但是np.arange创建索引0-599和0-799。然后必须将它们从形状(600,)和(800,)重塑为形状(600,1)和(800,1)。然后,我使用numpy.repeat分别复制数组800和600次,以实现形状为(600,800)和(800,600)的2D数组。最后,我将后者换位以实现两个2D形状的数组(600、800),第一个数组具有行的索引,第二个数组具有列的索引。

arr = np.empty((600,800,2))

# x_indices = [0 1 2 ... 597 598 599]
x_indices = np.arange(600)

# x_indices from shape (600,) to (600,1)
x_indices = x_indices.reshape(600,1)

# duplicate x_indices 800 times:
#              <-----------800------------->
# x_indices = [[  0   0   0 ...   0   0   0]] ^
#             [[  1   1   1 ...   1   1   1]] |
#             [[  2   2   2 ...   2   2   2]] |
#             ...                            600
#             [[597 597 597 ... 597 597 597]] |
#             [[598 598 598 ... 598 598 598]] |
#             [[599 599 599 ... 599 599 599]] V
x_indices = np.repeat(x_indices, 800, axis=1)


# y_indices = [0 1 2 ... 797 798 799]
y_indices = np.arange(800)

# y_indices from shape (800,) to (800,1)
y_indices = y_indices.reshape(800,1)

# duplicate y_indices 600 times:
#              <-----------600------------->
# y_indices = [[  0   0   0 ...   0   0   0]] ^
#             [[  1   1   1 ...   1   1   1]] |
#             [[  2   2   2 ...   2   2   2]] |
#             ...                            800
#             [[797 797 797 ... 797 797 797]] |
#             [[798 798 798 ... 798 798 798]] |
#             [[799 799 799 ... 799 799 799]] V
y_indices = np.repeat(y_indices, 600, axis=1)

# transpose y_indices
#              <---------800---------->
# y_indices = [[0 1 2 ... 797 798 799]] ^
#             [[0 1 2 ... 797 798 799]] |
#             [[0 1 2 ... 797 798 799]] |
#             ...                      600
#             [[0 1 2 ... 797 798 799]] |
#             [[0 1 2 ... 797 798 799]] |
#             [[0 1 2 ... 797 798 799]] V
y_indices = y_indices.T

arr[:,:,0] = x_indices
arr[:,:,1] = y_indices