2011-01-07 9 views
15

Ich versuche, ein nupy Array in kleinere Größe zu gruppieren, indem man den Durchschnitt der Elemente nimmt. Nehmen wir zum Beispiel durchschnittliche foreach 5x5 Sub-Arrays in einem 100x100 Array um ein 20x20 Array zu erstellen. Da ich riesige Datenmengen manipulieren muss, ist das ein effizienter Weg, dies zu tun?Gruppierung von 2D-Numpy-Arrays im Durchschnitt

+0

ähnlich wie [dieser] (https://stackoverflow.com/questions/18645013/windowed-maximum-in-numpy/18645174#18645174) als auch beantworten. – Daniel

Antwort

23

habe ich versucht, dies für kleinere Array, so testen Sie es mit Ihren:

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) 

Ein Beispiel mit 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

Das ist ziemlich einfach, obwohl ich das Gefühl, es könnte schneller sein:

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

Sie auch interessante scipy.signal.decimate finden könnte. Vor dem Downsampling der Daten wird ein ausgefeilterer Tiefpassfilter als eine einfache Mittelwertbildung angewendet, obwohl Sie eine Achse und dann die andere Achse dezimieren müssen.

2

Durchschnitt ein 2D-Array über Sub-Arrays der Größe NxN:

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

Nice one! Nur eine Klarstellung, dass Durchschnitt und Split numpy Funktionen sind. – MonkeyButter

0

Beachten Sie, dass eumiro's approach nicht maskierten Arrays funktioniert wie .mean(3).mean(1) als vermutet, dass jeder Mittelwert entlang der Achse 3 aus der gleichen Anzahl von Werten berechnet wurde. Wenn in Ihrem Array maskierte Elemente vorhanden sind, gilt diese Annahme nicht mehr. In diesem Fall müssen Sie die Anzahl der zur Berechnung verwendeten Werte überwachen und .mean(1) durch einen gewichteten Mittelwert ersetzen. Die Gewichte sind die normalisierte Anzahl von Werten, die zum Berechnen .mean(3) verwendet werden. Hier

ein Beispiel:

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