2016-03-02 17 views
5

Ich habe eine Matrix mit Form (64,17) entsprechen der Zeit & Breite. Ich möchte einen gewichteten Breitenmittelwert nehmen, von dem ich weiß, dass np.average dies kann, weil im Gegensatz zu np.nanmean, mit dem ich die Längenwerte durchschnitt, Gewichte in den Argumenten verwendet werden können. Np.average ignoriert NaN jedoch nicht wie np.nanmean, daher sind meine ersten 5 Einträge jeder Zeile in der Breitenmittelung enthalten und machen die gesamte Zeitreihe mit NaN voll.Nehmen Sie nP.-Durchschnitt, während Sie NaN ignorieren?

Gibt es eine Möglichkeit, einen gewichteten Durchschnitt zu nehmen, ohne dass die NaN in die Berechnung einbezogen werden?

file = Dataset("sst_aso_1951-2014latlon_seasavgs.nc") 
sst = file.variables['sst'] 
lat = file.variables['lat'] 

sst_filt = np.asarray(sst) 
missing_values_indices = sst_filt < -8000000 #missing values have value -infinity 
sst_filt[missing_values_indices] = np.nan  #all missing values set to NaN 

weights = np.cos(np.deg2rad(lat)) 
sst_zonalavg = np.nanmean(sst_filt, axis=2) 
print sst_zonalavg[0,:] 
sst_ts = np.average(sst_zonalavg, axis=1, weights=weights) 
print sst_ts[:] 

Ausgang:

[ nan nan nan nan nan 
27.08499908 27.33333397 28.1457119 28.32899857 28.34454346 
28.27285767 28.18571472 28.10199928 28.10812378 28.03411865 
28.06411552 28.16529465] 

[ nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan 
nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan 
nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan 
nan nan nan nan] 

Antwort

4

Sie können eine maskierte Array wie folgt erstellen:

data = np.array([[1,2,3], [4,5,np.NaN], [np.NaN,6,np.NaN], [0,0,0]]) 
cleaned_data = np.ma.masked_array(data,np.isnan(dat)) 
#calculate your weighted average here instead 
weights=[1,1,1] 
average = np.ma.average(cleaned_data,axis=1,weights=weights) 
#this gives you the result 
print average.filled(np.nan) 

Diese Ausgänge:

[ 2. 4.5 6. 0. ] 
+0

Ich erwähnte, dass ich np.nanmean nicht verwenden kann, weil es Gewichte in seinen Argumenten nicht nimmt. Ich versuche einen gewichteten Durchschnitt zu machen. – ChristineB

+0

Ich habe die Antwort aktualisiert, um ein maskiertes Array zu verwenden und 'np.mean' – Jaco

+0

Ich war im Begriff, eine Erwähnung in den ursprünglichen Beitrag zu bearbeiten, dass, da ich eine Zeitreihe mache, das Entfernen des NaN aus den Daten auch eine Option ist, aber du hast mich dazu geschlagen! – ChristineB

3

Sie können einfach die Eingabe-Array multiplizieren mit die weights und Summe entlang der angegebenen Achse Ignorieren NaNs mit np.nansum. So für Ihren Fall, vorausgesetzt, die weightssst_filt entlang axis = 1 auf dem Eingangs-Array verwendet werden sollen, wäre es -

np.nansum(sst_filt*weights,axis=1) 

für einen allgemeinen Fall eine Funktion definiert werden wie folgt -

def nanaverage(A,weights,axis): 
    return np.nansum(A*weights,axis=axis) 

Probelauf -

In [200]: sst_filt # 2D array case 
Out[200]: 
array([[ 0., 1.], 
     [ nan, 3.], 
     [ 4., 5.]]) 

In [201]: weights 
Out[201]: array([ 0.25, 0.75]) 

In [202]: nanaverage(sst_filt,weights=weights,axis=1) 
Out[202]: array([ 0.75, 2.25, 4.75]) 
2

ich würde wahrscheinlich den Teil des Arrays nur auswählen, die nicht NaN ist und dann diese Indizes verwenden, um die weig zu wählen das auch.

Zum Beispiel:

import numpy as np 
data = np.random.rand(10) 
weights = np.random.rand(10) 
data[[2, 4, 8]] = np.nan 

print data 
# [ 0.32849204, 0.90310062,   nan, 0.58580299,   nan, 
# 0.934721 , 0.44412978, 0.78804409,   nan, 0.24942098] 

ii = ~np.isnan(data) 
print ii 
# [ True True False True False True True True False True] 

result = np.average(data[ii], weights = weights[ii]) 
print result 
# .6470319 

Edit: Ich erkennen dies wird mit zweidimensionalen Anordnungen nicht. In diesem Fall würde ich wahrscheinlich nur die Werte und Gewichte für die NaNs auf Null setzen. Dies führt zu demselben Ergebnis, als wenn diese Indizes einfach nicht in die Berechnung einbezogen würden.

vor dem Einlaufen np.average:

data[np.isnan(data)] = 0; 
weights[np.isnan(data)] = 0; 
result = np.average(data, weights=weights) 

oder Kopien erstellen, wenn Sie den Überblick behalten wollen, von denen Indizes NaN waren.