[英]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.