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)