2011-01-07 177 views
15

我想通过取平均值将一个numpy数组分组为较小的大小。比如在一个100x100阵列中取平均每个5x5子阵列来创建一个20x20大小的阵列。由于我有一个庞大的数据需要操纵,这是一个有效的方式来做到这一点?平均分组2D numpy数组

+0

类似于[此](https://stackoverflow.com/questions/18645013/windowed-maximum-in-numpy/18645174#18645174)回答为好。 – Daniel 2017-12-17 03:54:07

回答

23

我曾尝试这对于较小的阵列,所以与你的测试:

import numpy as np 

nbig = 100 
nsmall = 20 
big = np.arange(nbig * nbig).reshape([nbig, nbig]) # 100x100 

small = big.reshape([nsmall, nbig//nsmall, nsmall, nbig//nsmall]).mean(3).mean(1) 

与6x6的一个例子 - >的3x3:

nbig = 6 
nsmall = 3 
big = np.arange(36).reshape([6,6]) 
array([[ 0, 1, 2, 3, 4, 5], 
     [ 6, 7, 8, 9, 10, 11], 
     [12, 13, 14, 15, 16, 17], 
     [18, 19, 20, 21, 22, 23], 
     [24, 25, 26, 27, 28, 29], 
     [30, 31, 32, 33, 34, 35]]) 

small = big.reshape([nsmall, nbig//nsmall, nsmall, nbig//nsmall]).mean(3).mean(1) 

array([[ 3.5, 5.5, 7.5], 
     [ 15.5, 17.5, 19.5], 
     [ 27.5, 29.5, 31.5]]) 
4

这是非常简单的,但我觉得它可能会更快:

from __future__ import division 
import numpy as np 
Norig = 100 
Ndown = 20 
step = Norig//Ndown 
assert step == Norig/Ndown # ensure Ndown is an integer factor of Norig 
x = np.arange(Norig*Norig).reshape((Norig,Norig)) #for testing 
y = np.empty((Ndown,Ndown)) # for testing 
for yr,xr in enumerate(np.arange(0,Norig,step)): 
    for yc,xc in enumerate(np.arange(0,Norig,step)): 
     y[yr,yc] = np.mean(x[xr:xr+step,xc:xc+step]) 

您也可能会发现scipy.signal.decimate有趣。在对数据进行下采样之前,它应用比简单平均更复杂的低通滤波器,但是必须对一个轴进行抽取,然后对另一个轴进行抽取。

2

平均值大小为NxN的子阵列的2D阵列:

height, width = data.shape 
data = average(split(average(split(data, width // N, axis=1), axis=-1), height // N, axis=1), axis=-1) 
+1

不错的一个!只是澄清,平均和分裂是numpy功能。 – MonkeyButter 2015-11-23 06:17:40

0

注意eumiro's approach不适用于蒙面数组作为.mean(3).mean(1)作为工作假设每个平均沿着轴3是从相同数量的值计算的。如果阵列中有被掩盖的元素,这个假设不再适用。在这种情况下,您必须跟踪用于计算.mean(3)的值的数量并用加权平均值代替.mean(1)。权重是用于计算.mean(3)的标准化数值。

下面是一个例子:

import numpy as np 


def gridbox_mean_masked(data, Nbig, Nsmall): 
    # Reshape data 
    rshp = data.reshape([Nsmall, Nbig//Nsmall, Nsmall, Nbig//Nsmall]) 

    # Compute mean along axis 3 and remember the number of values each mean 
    # was computed from 
    mean3 = rshp.mean(3) 
    count3 = rshp.count(3) 

    # Compute weighted mean along axis 1 
    mean1 = (count3*mean3).sum(1)/count3.sum(1) 
    return mean1 


# Define test data 
big = np.ma.array([[1, 1, 2], 
        [1, 1, 1], 
        [1, 1, 1]]) 
big.mask = [[0, 0, 0], 
      [0, 0, 1], 
      [0, 0, 0]] 
Nbig = 3 
Nsmall = 1 

# Compute gridbox mean 
print gridbox_mean_masked(big, Nbig, Nsmall)