2013-02-17 195 views
11

我正在尋找一個快速的公式來做一個2D numpy數組的數值裝倉。通過binning我的意思是計算子矩陣的平均值或累計值。例如。 x = numpy.arange(16).reshape(4,4)將被分解爲2x2的4個子矩陣,並給出numpy.array([[2.5,4.5],[10.5,12.5]]),其中2.5 = numpy。平均([0,1,4,5])等...Numpy重組2D數組

如何以有效的方式執行這樣的操作...我真的沒有任何想法如何執行此操作...

非常感謝...

+0

是保證,以適應小矩陣,到底是什麼?你有1.7嗎?可用(這就是整潔,沒有必要)? – seberg 2013-02-17 00:59:01

+0

我已經numpy 1.8dev,但我的工作得到舊版本... – user1187727 2013-02-17 15:31:39

回答

17

您可以使用陣列的高維視圖,並取平均值沿額外維度:

In [12]: a = np.arange(36).reshape(6, 6) 

In [13]: a 
Out[13]: 
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]]) 

In [14]: a_view = a.reshape(3, 2, 3, 2) 

In [15]: a_view.mean(axis=3).mean(axis=1) 
Out[15]: 
array([[ 3.5, 5.5, 7.5], 
     [ 15.5, 17.5, 19.5], 
     [ 27.5, 29.5, 31.5]]) 

在一般情況下,如果你想要的形狀(a, b)的垃圾箱爲(rows, cols)數組,你對它的重塑應該是.reshape(rows // a, a, cols // b, b)。還要注意的是,.mean的順序是重要的,例如, a_view.mean(axis=1).mean(axis=3)會引發錯誤,因爲a_view.mean(axis=1)只有三個維度,儘管a_view.mean(axis=1).mean(axis=2)可以正常工作,但它會使得更難理解正在發生的事情。

AS是,上面的代碼只工作,如果如果a劃分rowsb劃分cols可以適合你的數組內箱的整數倍,即。有辦法處理其他情況,但是你必須定義你想要的行爲。

+4

在numpy 1.7。你可以將它壓縮到'.mean(axis =(1,3))'! – seberg 2013-02-17 01:19:27

+1

我不知道這個重塑是可能的,太棒了!不幸的是,平均值是按照順序依賴的,因此如何獲得前者的平均值。在你的例子中的2,2的子矩陣(我的意思是角0,1,6,7等)? – user1187727 2013-02-17 15:29:48

+1

@ user1187727我不認爲我理解你的問題,但是'[[0,1],[6,7]]'的平均值是'a_view.mean(axis = 1)'的項['0,0] 3).mean(軸= 1)'。 – Jaime 2013-02-17 15:36:14

0

我假設你只想知道如何通常構建一個功能,可以很好地執行和數組操作,就像你的例子中的numpy.reshape一樣。因此,如果性能真的很重要,並且您已經在使用numpy,那麼您可以編寫自己的C代碼,比如numpy。例如,arange的實現完全在C中。幾乎所有與性能有關的numpy都是在C中實現的。

但是,在這樣做之前,應該嘗試在python中實現代碼並查看性能是夠好的。儘量讓python代碼儘可能高效。如果它仍然不適合您的性能需求,請使用C方式。

你可以在docs的地方閱讀。

1

the SciPy Cookbook on rebinning,它提供了這個片斷:

def rebin(a, *args): 
    '''rebin ndarray data into a smaller ndarray of the same rank whose dimensions 
    are factors of the original dimensions. eg. An array with 6 columns and 4 rows 
    can be reduced to have 6,3,2 or 1 columns and 4,2 or 1 rows. 
    example usages: 
    >>> a=rand(6,4); b=rebin(a,3,2) 
    >>> a=rand(6); b=rebin(a,2) 
    ''' 
    shape = a.shape 
    lenShape = len(shape) 
    factor = asarray(shape)/asarray(args) 
    evList = ['a.reshape('] + \ 
      ['args[%d],factor[%d],'%(i,i) for i in range(lenShape)] + \ 
      [')'] + ['.sum(%d)'%(i+1) for i in range(lenShape)] + \ 
      ['/factor[%d]'%i for i in range(lenShape)] 
    print ''.join(evList) 
    return eval(''.join(evList))