2016-03-02 25 views
5

Mam matrycę o kształcie (64,17) odpowiada czasowi & szerokości geograficznej. Chcę wziąć średnią ważoną szerokość geograficzną, o której wiem, że np.average może zrobić, ponieważ, w przeciwieństwie do np.nanmean, którą zwykłem uśredniać długości, w argumentach można stosować wagi. Jednak np.average nie ignoruje NaN jak np.nanmean, więc moje pierwsze 5 wpisów z każdego rzędu są ujęte w uśrednianiu szerokości i sprawiają, że cała seria czasowa jest pełna NaN.Biorąc np.average ignorując NaN's?

Czy istnieje sposób, aby wziąć średnią ważoną bez uwzględnienia NaN w obliczeniach?

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[:] 

wyjściowa:

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

Odpowiedz

4

Można utworzyć zamaskowany tablicę takiego:

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) 

This Wyjścia:

[ 2. 4.5 6. 0. ] 
+0

Wspomniałem, że nie mogę używać np.nanmean, ponieważ nie bierze on wagi w swoich argumentach. Próbuję zrobić średnią ważoną. – ChristineB

+0

Zaktualizowałem odpowiedź, aby użyć zamaskowanej tablicy i 'np.mean' – Jaco

+0

miałem zamiar edytować wzmiankę w oryginalnym wpisie, że ponieważ robię szereg czasowy, usunięcie NaN z danych jest również opcją, ale mnie biłeś! – ChristineB

3

można po prostu pomnożyć macierz wejściowy weights i suma wzdłuż określonej osi ignorując NaNs z np.nansum. Tak więc w Twoim przypadku, zakładając weights mają być używane wraz axis = 1 na tablicy wejściowej sst_filt, byłoby -

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

Dla ogólnego przypadku, funkcja może być zdefiniowana w następujący sposób -

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

Sample Run -

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

bym chyba tylko wybrać część tablicy, która nie jest NaN, a następnie wykorzystać te indeksy wybrać Weig też.

Na przykład:

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: zdałem sobie sprawę, to nie będzie działać z dwóch tablic wymiarowych. W takim przypadku prawdopodobnie ustawiłbym wartości i wagi na zero dla NaN. Daje to taki sam wynik, jak gdyby te wskaźniki nie zostały uwzględnione w obliczeniach.

przed uruchomieniem np.average:

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

Albo tworzyć kopie, jeśli chcesz śledzić których indeksy Nan.