如何有效地创建一个多维的numpy数组,其条目仅取决于一个维度索引?

时间:2017-04-11 14:13:07

标签: python arrays performance numpy multidimensional-array

如何使用内置函数更有效地创建以下numpy数组?

import numpy as np
MyArray = np.zeros([10,10,10,10,10])
for i in range(10):
    for j in range(10):
        for k in range(10):
            for l in range(10):
                for m in range(10):
                    MyArray[i,j,k,l,m] = l

如您所见,元素仅取决于其中一个维度索引。我尝试使用numpy.tile但到目前为止无法弄明白。

4 个答案:

答案 0 :(得分:4)

看起来你在np.broadcast_to之后:

# build an array where l_vals[0,0,0,i,0] = i
l_vals = np.arange(10).reshape(1, 1, 1, -1, 1)

# duplicate that array, without copies, in the other axes
l_grid = np.broadcast_to(l_vals, (10, 10, 10, 10, 10))

值得注意的是broadcast_to返回一个只读数组,因为元素实际上共享内存位置。如果您想在创建后写入此内容,则可以拨打np.copy,或使用tile代替:

l_grid = np.tile(l_vals, (10, 10, 10, 1, 10))

你也可以将你的循环弄平:

MyArray = np.zeros([10,10,10,10,10])
for l in range(10):
    MyArray[:,:,:,l,:] = l

答案 1 :(得分:3)

这是initialization -

的方法
n = 10
a = np.empty((n,n,n,n,n),dtype=int)
a[...] = np.arange(n)[:,None]

这是另一种基于NumPy strides的方法 -

r = np.arange(n)
s = r.strides[0]
shp = (n,n,n,n,n)
out = np.lib.index_tricks.as_strided(r, shape=shp, strides=(0,0,0,s,0))

运行时测试

方法 -

# @Eric's soln1
def broadcast_to_based(n): # Creates a read-only array
    l_vals = np.arange(n).reshape(1, 1, 1, -1, 1)
    return np.broadcast_to(l_vals, (n, n, n, n, n))

# @Eric's soln2    
def tile_based(n):
    l_vals = np.arange(n).reshape(1, 1, 1, -1, 1)
    return np.tile(l_vals, (n, n, n, 1, n))

# @kmichael08's soln          
def fromfunc_based(n):
    return np.fromfunction(lambda i, j, k, l, m : l, (n, n, n, n, n))

# @Tw UxTLi51Nus's soln
def loop_based(n): 
    MyArray = np.zeros([n,n,n,n,n],dtype=int)
    for l in range(n):
        MyArray[:, :, :, l, :] = l
    return MyArray

# Proposed-1 in this post      
def initialization_based(n):
    a = np.empty((n,n,n,n,n),dtype=int)
    a[...] = np.arange(n)[:,None]
    return a

# Proposed-2 in this post      
def strided_based(n):
    r = np.arange(n)
    s = r.strides[0]
    shp = (n,n,n,n,n)
    return np.lib.index_tricks.as_strided(r, shape=shp, strides=(0,0,0,s,0))

计时 -

In [153]: n = 10
     ...: %timeit broadcast_to_based(n)
     ...: %timeit tile_based(n)
     ...: %timeit fromfunc_based(n)
     ...: %timeit loop_based(n)
     ...: %timeit initialization_based(n)
     ...: %timeit strided_based(n)
     ...: 
100000 loops, best of 3: 4.1 µs per loop
1000 loops, best of 3: 236 µs per loop
1000 loops, best of 3: 645 µs per loop
10000 loops, best of 3: 180 µs per loop
10000 loops, best of 3: 89.1 µs per loop
100000 loops, best of 3: 5.44 µs per loop

In [154]: n = 20
     ...: %timeit broadcast_to_based(n)
     ...: %timeit tile_based(n)
     ...: %timeit fromfunc_based(n)
     ...: %timeit loop_based(n)
     ...: %timeit initialization_based(n)
     ...: %timeit strided_based(n)
     ...: 
100000 loops, best of 3: 4.05 µs per loop
100 loops, best of 3: 8.16 ms per loop
10 loops, best of 3: 24.1 ms per loop
100 loops, best of 3: 6.07 ms per loop
100 loops, best of 3: 2.31 ms per loop
100000 loops, best of 3: 5.48 µs per loop

答案 2 :(得分:2)

尝试np.fromfunction,在你的情况下,它会是这样的: MyArray = np.fromfunction(lambda i, j, k, l, m : l, (10, 10, 10, 10, 10))

答案 3 :(得分:2)

您可以通过一个循环执行此操作:

import numpy as np
MyArray = np.zeros([10,10,10,10,10])

for l in range(10):
    MyArray[:, :, :, l, :] = l

显然,您也可以将此作为列表理解。