我有一个numpy形状的阵列(10,10,10,60)。尺寸可以是任意的,但这只是一个例子。
我希望通过对某些子集取平均值来将其减少为(10, 10, 10, 20)
数组我有两种情况:
1 :取每个(10, 10, 10, 20)
块的平均值,即有三个(10, 10, 10, 20)
块并取三者之间的平均值。这可以通过以下方式完成:m = np.mean((x[..., :20], x[..., 20:40], x[...,40:60]), axis=3)
。我的问题是,如果最后一个维度是任意的而不编写一些显式循环,我该如何生成这个?所以,我可以这样做:
x = np.random.rand(10, 10, 10, 60)
result = np.zeros((10, 10, 10, 20))
offset = 20
loops = x.shape[3] // offset
for i in range(loops):
index = i * offset
result += x[..., index:index+offset]
result = result / loops
然而,这似乎不太过于pythonic,我想知道是否有更优雅的方式来做到这一点。
2 :另一种情况是我想将其分解为10个形状(10, 10, 10, 2, 3)
的数组,然后在这10个数组之间沿第5维度取平均值然后重新整形原始计划的(10, 10, 10, 20)
数组。我可以重新塑造阵列然后再次采用之前的平均值并再次重塑,但第二部分似乎非常不优雅。
答案 0 :(得分:1)
你可以重新分割最后一个轴为两个,这样第一个轴的长度就像所需的块数一样,然后得到沿倒数第二个轴的平均值/平均值 -
m,n,r = x.shape[:3]
out = x.reshape(m,n,r,3,-1).mean(axis=-2) # 3 is no. of blocks
或者,我们可以引入np.einsum
以获得显着的性能提升 -
In [200]: x = np.random.rand(10, 10, 10, 60)
In [201]: %timeit x.reshape(m,n,r,3,-1).mean(axis=-2)
1000 loops, best of 3: 430 µs per loop
In [202]: %timeit np.einsum('ijklm->ijkm',x.reshape(m,n,r,3,-1))/3.0
1000 loops, best of 3: 214 µs per loop