简体   繁体   English

将形状为 (x,y,z) 和 (x,) 的 numpy 数组相乘和求和

[英]Multiply and sum numpy arrays with shapes (x,y,z) and (x,)

So I have a 3D data-set (x,y,z), and i want to sum over one of the axes (x) with a set of weights, w = w(x).所以我有一个 3D 数据集 (x,y,z),我想用一组权重对一个轴 (x) 求和,w = w(x)。 The start and end index i am summing over is different for every (y,z), I have solved this by masking the 3D-array.我求和的开始和结束索引对于每个 (y,z) 都是不同的,我通过屏蔽 3D 数组解决了这个问题。 The weights are constant with regard to the two variables i am not summing over.对于我没有总结的两个变量,权重是恒定的。 Both answers regarding implementation and mathematics are appreciated (is there a smart linalg. way of doing this?).关于实现和数学的两个答案都受到赞赏(是否有一个聪明的 linalg。这样做的方法?)。

I have a 3D masked array (A) of shape (x,y,z) and a 1D array (t) of shape (x,).我有一个形状为 (x,y,z) 的 3D 掩码数组 (A) 和一个形状为 (x,) 的一维数组 (t)。 Is there a good way to multiply every (y,z) element in A with the corresponding number in t without expanding t to a 3D array?有没有一种好方法可以将 A 中的每个 (y,z) 元素与 t 中的相应数字相乘,而无需将 t 扩展为 3D 数组? My current solution is using np.tensordot to make a 3D array of the same shape as A, that holds all the t-values, but it feels very unsatisfactory to spend runtime building the "new_t" array, which is essensially just y*z copies of t.我目前的解决方案是使用 np.tensordot 制作一个与 A 形状相同的 3D 数组,该数组包含所有 t 值,但是花费运行时间构建“new_t”数组感觉非常不令人满意,这基本上只是 y*z t 的副本。

Example of current solution:当前解决方案示例:

a1 = np.array([[1,2,3,4],
               [5,6,7,8],
               [9,10,11,12]])

a2 = np.array([[0,1,2,3],
               [4,5,6,7],
               [8,9,10,11]])

#note: A is a masked array, mask is a 3D array of bools
A = np.ma.masked_array([a1,a2],mask)
t = np.array([10,11])

new_t = np.tensordot(t, np.ones(A[0].shape), axes = 0)
return np.sum(A*new_t, axis=0)

In essence i want to perform t*A[:,i,j] for all i,j with the shortest possible runtime, preferably without using too many other libraries than numpy and scipy.本质上,我想以尽可能短的运行时间为所有 i,j 执行 t*A[:,i,j],最好不使用除 numpy 和 scipy 之外的太多其他库。

Another way of producing desired output (again, with far too high run time):另一种产生所需输出的方法(同样,运行时间太长):

B = [[t*A[:,i,j] for j in range(A.shape[2])] for i in range(A.shape[1])]
return np.sum(B,axis=2)

inspired by @phipsgabler comment灵感来自@phipsgabler 评论

arr1 = np.tensordot(A.T,t,axes=1).T
arr1
array([[ 10,  31,  52,  73],
       [ 94, 115, 136, 157],
       [178, 199, 220, 241]])

Thanks for good answers!谢谢你的好答案! Using tensordot like @alyhosny proposed worked, but replacing masked values with zeros using使用像@alyhosny 建议的 tensordot 工作,但使用零替换掩码值

A = np.ma.MaskedArray.filled(A,0)

before summing with einsum (thanks @phipsgabler) gave half the run time.在用 einsum 求和之前(感谢@phipsgabler)给了一半的运行时间。 Final code:最终代码:

A = np.ma.MaskedArray(A,mask)
A = np.ma.MaskedArray.filled(A,0)
return np.einsum('ijk,i->jk',A,t)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM