2013-02-17 15 views
11

Ich bin auf der Suche nach einer schnellen Formulierung, um eine numerische Binning einer 2D-numpy-Array zu tun. Mit Binning meine ich Submatrix-Mittelwerte oder kumulative Werte zu berechnen. Für Beispiel x = numpy.arange (16) .reshape (4, 4) wäre in 4 Untermatrizen von jeweils 2x2 geteilt worden und ergibt numpy.array ([[2,5,4,5], [10,5,12,5]]) mit 2,5 = numpy. Durchschnitt ([0,1,4,5]) usw. ...Numpy Rebinning ein 2D-Array

So führen Sie einen solchen Vorgang auf effiziente Weise aus ... Ich habe wirklich keine Idee, wie Sie das ausführen können ...

Vielen dank ...

+0

Sind die Untermatrizen garantiert passen genau? hast du numpige 1.7? verfügbar (das ist nur ordentlich, nicht notwendig)? – seberg

+0

Ich habe numpy 1.8dev, aber mein Job wird ältere Version ... – user1187727

Antwort

17

Sie können einen höherdimensionalen Ansicht Ihres Arrays verwenden und die durchschnittliche entlang der zusätzlichen Dimensionen annehmen:

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]]) 

Im Allgemeinen, wenn Sie Bins Form wollen (a, b) für eine Reihe von (rows, cols), Ihre Umbildung davon sollte .reshape(rows // a, a, cols // b, b) sein. Man beachte auch, dass die Reihenfolge der .mean wichtig ist, z. a_view.mean(axis=1).mean(axis=3) wird einen Fehler verursachen, weil a_view.mean(axis=1) nur drei Dimensionen hat, obwohl a_view.mean(axis=1).mean(axis=2) wird gut funktionieren, aber es macht es schwerer zu verstehen, was vor sich geht.

Wie ist, der obige Code funktioniert nur, wenn Sie eine ganze Anzahl von Bins in Ihrem Array passen, das heißt, wenn arows teilt und teilt bcols. Es gibt Möglichkeiten, mit anderen Fällen umzugehen, aber Sie müssen dann das gewünschte Verhalten definieren.

+4

Auf numpy 1.7. Sie können es zusammen in '.mean (Achse = (1,3))' zerquetschen! – seberg

+1

Ich wusste nicht, dass diese Umformung möglich wäre, großartig! Leider ist der Durchschnitt abhängig davon geordnet, wie man den Durchschnitt von ex erhält. eine Untermatrix von 2,2 in deinem Beispiel (ich meine die Ecke 0,1,6,7 usw.)? – user1187727

+1

@ user1187727 Ich glaube nicht, dass ich deine Frage verstehe, aber der Durchschnitt von '[[0, 1], [6, 7]]' ist das Element '[0, 0]' von 'a_view.mean (axis = 3) .mean (Achse = 1) '. – Jaime

0

ich gehe davon aus, dass Sie nur wissen wollen, wie im allgemeinen eine Funktion erstellen, die mit Arrays gut und tun etwas führt, so wie numpy.reshape in Ihrem Beispiel. Wenn Leistung wirklich zählt und Sie bereits numpy verwenden, können Sie dafür Ihren eigenen C-Code schreiben, wie es bei numpy der Fall ist. Zum Beispiel ist die Implementierung von arange vollständig in C. Fast alles mit numpy, was die Leistung angeht, ist in implementiert. Bevor Sie dies tun, sollten Sie jedoch versuchen, den Code in Python zu implementieren und sehen, ob die Leistung ist gut genug. Versuchen Sie, den Python-Code so effizient wie möglich zu machen. Wenn es immer noch nicht Ihren Leistungsanforderungen entspricht, gehen Sie die C-Art.

Sie können darüber in der docs lesen.

1

See the SciPy Cookbook on rebinning, die diese Schnipsel sieht vor:

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))