numpy的:从一个阵列整合尺寸到另一个
问题描述:
鉴于两个阵列一个(形状= a, b, c, d, e
)和b(形状= a, x, b
),我想的bx
包括尺寸成一个 ,这样一个新的阵列c导致形状= a, x, b, c, d, e
。的b值应均匀分布:numpy的:从一个阵列整合尺寸到另一个
c.sum(1) == a
b.sum(1) == a.sum(axis=(2, 3, 4)) == c.sum(axis=(1, 3, 4, 5)
是否有这样做,这是一个几行numpy的或者是有必要在所有迭代的任何聪明的办法手动值b[x]
?
我目前的解决方案:
for a, x, b in zip(*_b_.nonzero()):
tot = _a_[a, b].sum()
for c, d, e in zip(*_a_[a, b].nonzero()):
val = _b_[a, a, b]
frac = _a_[a, b, c, d, e]/tot
_c_[a, x, b, c, d, e] = val * frac
答
这是一种方式,三线要做到这一点,但首先一些关于我的做法的话:
- 为了更好的符号,我将使用大写字母矩阵和索引的小写字母。所以我们有
A[a,b,c,d,e]
和B[a,x,b]
作为输入。 - 根据您的代码,
C
对于所有x
都是一样的,所以我们并不真的需要该轴进行计算(如果需要,您可以将其添加为新维度并在之后复制条目)。 -
B[a,a,b]
可以沿着前两个轴取对角线。 -
tot
超过指数c,d,e
的总和,我们可以在这个存储在预先计算阵列Tot[a,b]
- 能在最后一步使用
numpy.einsum
,我会先采取逆Tot = 1/Tot
这里是完整的代码:
import numpy
# generate some example input
a = 2
b = 3
c = 4
d = 5
e = 6
x = 7
A = numpy.arange(a*b*c*d*e).reshape((a,b,c,d,e))
B = numpy.arange(a*x*b).reshape((a,x,b))
C = numpy.zeros((a,x,b,c,d,e))
# solution by orange
for a, x, b in zip(*B.nonzero()):
tot = A[a, b].sum()
for c, d, e in zip(*A[a, b].nonzero()):
val = B[a, a, b]
frac = A[a, b, c, d, e]/tot
C[a, x, b, c, d, e] = val * frac
# new solution
B2 = numpy.diagonal(B, axis1=0, axis2=1).transpose() # contract B_aab -> B2_ab
Tot = 1/numpy.sum(A, (2,3,4)) # contract \sum_cde A_abcde -> 1/Tot_ab
C2 = numpy.einsum('ab,abcde,ab->abcde',B2,A,Tot)
# compare (should print x times True)
for i in range(C.shape[1]):
C_ = C[:,i,:,:,:]
print(numpy.all(numpy.isclose(C_,C2)))
编辑:如果numpy.einsum()
是你太慢了,你可以实现在用Cython与for
厕所的最后一步PS。
'c = a [:,None,...] + b [:,:,:None,None,None]'应该形成一个正确维度的新矩阵。缩放'a'或'b'可能会满足您的总和条件。我还没有研究他们足以说肯定。 – hpaulj
我用一些示例代码更新了描述。我不认为添加_a_和_b_会起作用... – orange
请大家帮忙,不要在维和变量中使用相同的变量名。它使你的代码和描述非常难以阅读。 –