2015-10-13 51 views
3

我有一个3维numpy数组A.我想用w *(i/Lx + j/1)乘以每个元素A [i,j, Ly + k/Lz)其中w,Lx,Ly和Lz是实数(浮点数)。在for循环中执行这个操作是非常不切实际的,因为我需要能够对大数组进行缩放,并且对于O(N^3)中的三个索引ijk进行for循环。应用函数,关心索引到numpy数组的每个元素

有没有一种有效的方法来执行一个关于索引的numpy数组的每个元素的操作?

+0

创建3 3D numpy的数组:I是像I [I,:,:] = I,J是像f] [:,J,:] = j和k [:,:,k]的= K。然后A * w *(I/Lx + J/Ly + K/Lz) –

回答

4

您可以使用broadcasting -

M,N,R = A.shape 

p1 = np.arange(M)[:,None,None]/Lx 
p2 = np.arange(N)[:,None]/Ly 
p3 = np.arange(R)/Lz 

out = A/(w*(p1 + p2 + p3)) 

您还可以使用np.ix_更优雅解决方案 -

M,N,R = A.shape 
X,Y,Z = np.ix_(np.arange(M),np.arange(N),np.arange(R)) 
out = A/(w*((X/Lx) + (Y/Ly) + (Z/Lz))) 

运行测试和输出验证 -

功能定义:

def vectorized_app1(A, w, Lx, Ly, Lz): 
    M,N,R = A.shape 
    p1 = np.arange(M)[:,None,None]/Lx 
    p2 = np.arange(N)[:,None]/Ly 
    p3 = np.arange(R)/Lz 
    return A/(w*(p1 + p2 + p3)) 

def vectorized_app2(A, w, Lx, Ly, Lz): 
    M,N,R = A.shape 
    X,Y,Z = np.ix_(np.arange(M),np.arange(N),np.arange(R)) 
    return A/(w*((X/Lx) + (Y/Ly) + (Z/Lz))) 

def original_app(A, w, Lx, Ly, Lz): 
    out = np.empty_like(A) 
    M,N,R = A.shape 
    for i in range(M): 
     for j in range(N): 
      for k in range(R): 
       out[i,j,k] = A[i,j,k]/(w*((i/Lx) + (j/Ly) + (k/Lz))) 
    return out 

时序:

In [197]: # Inputs 
    ...: A = np.random.rand(100,100,100) 
    ...: w, Lx, Ly, Lz = 2.3, 3.2, 4.2, 5.2 
    ...: 

In [198]: np.allclose(original_app(A,w,Lx,Ly,Lz),vectorized_app1(A,w,Lx,Ly,Lz)) 
Out[198]: True 

In [199]: np.allclose(original_app(A,w,Lx,Ly,Lz),vectorized_app2(A,w,Lx,Ly,Lz)) 
Out[199]: True 

In [200]: %timeit original_app(A, w, Lx, Ly, Lz) 
1 loops, best of 3: 1.39 s per loop 

In [201]: %timeit vectorized_app1(A, w, Lx, Ly, Lz) 
10 loops, best of 3: 24.6 ms per loop 

In [202]: %timeit vectorized_app2(A, w, Lx, Ly, Lz) 
10 loops, best of 3: 24.2 ms per loop