在numpy

时间:2017-01-26 13:22:54

标签: python numpy

我有一个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)数组。我可以重新塑造阵列然后再次采用之前的平均值并再次重塑,但第二部分似乎非常不优雅。

1 个答案:

答案 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