Python 创建numpy 2d索引数组的最快方法

Python 创建numpy 2d索引数组的最快方法,python,performance,numpy,vectorization,Python,Performance,Numpy,Vectorization,我想创建一个包含单元索引的numpy 2d数组,例如,可以使用以下方法创建2x2 mat: np.array([[[0,0],[0,1]],[[1,0],[1,1]]]) 换句话说,索引i,j处的单元格应包含列表[i,j] 我可以用c方式做一个嵌套循环,但我想知道是否有一种快速的Python方式可以做到这一点 np.array(list(product(range(n), repeat=2))).reshape(n,n,2) 对于NumPy的性能,我建议使用基于阵列初始化的方法- def i

我想创建一个包含单元索引的numpy 2d数组,例如,可以使用以下方法创建2x2 mat:

np.array([[[0,0],[0,1]],[[1,0],[1,1]]])
换句话说,索引
i,j
处的单元格应包含列表
[i,j]

我可以用c方式做一个嵌套循环,但我想知道是否有一种快速的Python方式可以做到这一点

np.array(list(product(range(n), repeat=2))).reshape(n,n,2)

对于NumPy的性能,我建议使用基于阵列初始化的方法-

def indices_array(n):
    r = np.arange(n)
    out = np.empty((n,n,2),dtype=int)
    out[:,:,0] = r[:,None]
    out[:,:,1] = r
    return out
对于一般的
(m,n,2)
形输出,我们需要进行一些修改:

def indices_array_generic(m,n):
    r0 = np.arange(m) # Or r0,r1 = np.ogrid[:m,:n], out[:,:,0] = r0
    r1 = np.arange(n)
    out = np.empty((m,n,2),dtype=int)
    out[:,:,0] = r0[:,None]
    out[:,:,1] = r1
    return out
注意:另外,请阅读本帖后面的2019年附录。使用大型
m
n
进行增压

样本运行-

In [145]: n = 3

In [146]: indices_array(n)
Out[146]: 
array([[[0, 0],
        [0, 1],
        [0, 2]],

       [[1, 0],
        [1, 1],
        [1, 2]],

       [[2, 0],
        [2, 1],
        [2, 2]]])
如果需要一个
2
columns
2D
数组,只需重新整形即可-

In [147]: indices_array(n).reshape(-1,2)
Out[147]: 
array([[0, 0],
       [0, 1],
       [0, 2],
       [1, 0],
       [1, 1],
       [1, 2],
       [2, 0],
       [2, 1],
       [2, 2]])
时间安排和核查-

In [141]: n = 100   
     ...: out1 = np.array(list(product(range(n), repeat=2))).reshape(n,n,2)
     ...: out2 = indices_array(n)
     ...: print np.allclose(out1, out2)
     ...: 
True

# @Ofek Ron's solution
In [26]: %timeit np.array(list(product(range(n), repeat=2))).reshape(n,n,2)
100 loops, best of 3: 2.69 ms per loop

In [27]: # @Brad Solomon's soln    
    ...: def ndindex_app(n):
    ...:    row, col = n,n
    ...:    return np.array(list(np.ndindex((row, col)))).reshape(row, col, 2)
    ...: 

# @Brad Solomon's soln 
In [28]: %timeit ndindex_app(n)
100 loops, best of 3: 5.72 ms per loop

# Proposed earlier in this post
In [29]: %timeit indices_array(n)
100000 loops, best of 3: 12.1 µs per loop

In [30]: 2690/12.1
Out[30]: 222.31404958677686
200x+
使用基于初始化的方法在
n=100
中加速


2019年补遗 我们也可以使用-

时间安排-

In [115]: %timeit indices_array_generic(1000,1000)
     ...: %timeit indices_array_generic_builtin(1000,1000)
100 loops, best of 3: 2.92 ms per loop
1000 loops, best of 3: 1.37 ms per loop
你想要的


单元索引是列表,我需要2d矩阵包含每个单元的单元索引。。。我同意这个结果是三维的,但这正是我需要的——它也比np.ndix快吗?@OfekRon为所有方法增加了计时。过来看!如果重新浇水的垫子不是正方形怎么办?e、 g给定行,列在ndindex?def create_索引(行,列)中计数:r=np.arange(行)c=np.arange(列)out=np.empty((行,列,2),dtype=int)out[:,:,0]=r[:,None]out[:,:,1]=c打印输出返回out@OfekRon查看刚刚添加的
索引\u数组\u generic
In [115]: %timeit indices_array_generic(1000,1000)
     ...: %timeit indices_array_generic_builtin(1000,1000)
100 loops, best of 3: 2.92 ms per loop
1000 loops, best of 3: 1.37 ms per loop
def coords(row, col):
    return np.array(list(np.ndindex((row, col)))).reshape(row, col, 2)

coords(3, 2)
Out[32]: 
array([[[0, 0],
        [0, 1]],

       [[1, 0],
        [1, 1]],

       [[2, 0],
        [2, 1]]])