如何做一个垂直水平的总和

时间:2017-11-20 18:53:43

标签: python python-2.7 for-loop

我正在尝试整合我的数据深度。我的数据是4D数据(341,50,120,100),其中我分别有时间,深度,i-pos,j-pos。我正在尝试应用以下等式....

Vf[t,i,j] = integral ((mean - data[t,zz,i,j]) x mean) x ( depth[zz,i,j] - depth[zz+1,i,j])

其中,

f = (mean - data)*mean

d_depth, i.e: abs(data[0,0,0,0]-data[0,1,0,0])

因此,

Vf = integral(f*d_depth)

尽管如此,我正在做的事情并不是那么有效。

for tt in range(sal.shape[0]):
    print('time',str(tt))
    for j in range(sal.shape[3]):
        print('j',str(j))
        for i in range(sal.shape[2]):
            print('i',str(i))
            for zz in range(sal.shape[1]-1):
                Vf[tt,i,j] += abs(grid[zz,i,j]-grid[zz+1,i,j])*f[tt,zz,i,j]

有人会知道如何以更好的方式做到这一点吗?

谢谢,

马修斯

1 个答案:

答案 0 :(得分:0)

从你的代码中划分我假设

  • f有4个维度:ttzzij
  • grid有3个维度:zzij
  • Vf有3个维度:ttij

虚假数据:

TT = 5
ZZ = 3
I = 5
J = 4
grid = np.random.randint(0, 255, (ZZ, I, J))
f = np.random.rand(TT,ZZ,I,J)

嵌套for循环可以矢量化

abs(grid[zz,i,j]-grid[zz+1,i,j])在第一个轴上基本上是numpy.diff(),可以在没有循环的情况下在完整数组上执行。

term1 = np.absolute(np.diff(grid, axis = 0))

term1的形状是(ZZ-1,I,J)。为了将其乘以fzz维度必须相同,以便f tt维度/轴上的乘法broadcast 。从最里面的循环语句中,我们看到zz的最后一个元素未被使用 - for zz in range(sal.shape[1]-1):

w = term1 * f[:,:-1,...]

Vf[tt,i,j] +=我们看到zz轴已消失,因此它正在对zz轴进行求和。

vf = w.sum(axis = 1)

...

term1 = np.absolute(np.diff(grid, axis = 0))
w = term1*f[:,:-1,...]
vf = w.sum(axis = 1)

通过嵌套for循环运行我的假数据:

Vf = np.zeros((TT,I,J))
for tt in range(TT):
##    print('time',str(tt))
    for j in range(J):
##        print('j',str(j))
        for i in range(I):
##            print('i',str(i))
            for zz in range(ZZ-1):
                Vf[tt,i,j] += abs(grid[zz,i,j]-grid[zz+1,i,j])*f[tt,zz,i,j]

vVf进行比较表示结果相同:

>>> np.all(Vf == vf)
True
>>> 

有一些 einsum 等价物有时会更快。

w = term1*f[:,:-1,...]可以替换为

w = np.einsum('ijkl, ijkl->ijkl',f[:,:-1,...], term1[None,...])

vf = w.sum(axis = 1)可以替换为

vf = np.einsum('wxyz->wyz', w)

将操作组合到单个einsum会产生明显的加速

vf = np.einsum('ijkl, ijkl->ikl',f[:,:-1,...], term1[None,...])