2016-10-07 148 views
2

我正試圖計算包含NaN的大型numpy數組中的移動平均數。目前我使用:使用NaNs計算numpy數組中的移動平均數

import numpy as np 

def moving_average(a,n=5): 
     ret = np.cumsum(a,dtype=float) 
     ret[n:] = ret[n:]-ret[:-n] 
     return ret[-1:]/n 

當使用屏蔽數組計算:

x = np.array([1.,3,np.nan,7,8,1,2,4,np.nan,np.nan,4,4,np.nan,1,3,6,3]) 
mx = np.ma.masked_array(x,np.isnan(x)) 
y = moving_average(mx).filled(np.nan) 

print y 

>>> array([3.8,3.8,3.6,nan,nan,nan,2,2.4,nan,nan,nan,2.8,2.6]) 

結果我要找(下)最好有NaN的只在地方原數組,X,曾NaN,並且平均應在非楠元素的數量來進行的分組(我需要一些方法來改變n的大小的功能。)

y = array([4.75,4.75,nan,4.4,3.75,2.33,3.33,4,nan,nan,3,3.5,nan,3.25,4,4.5,3]) 

我可以循環整個陣列過來, C heck index by index,但是我使用的數組非常大,這需要很長時間。有沒有一個numpythonic的方式來做到這一點?

+0

所以,是'[4.75,4.75,nan,4.4,3.75,2.33,3.33,4,nan,nan,3,3.5,nan,3.25]'預期的輸出?如果是這樣,爲什麼有一個「NaN」作爲第三個元素? – Divakar

+0

@Divakar這是預期的輸出。在原始數組(x)中,有一個「nan」作爲第三個條目。 – krakenwagon

+0

那麼,爲什麼我們有NaN作爲預期產出的倒數第二項呢? – Divakar

回答

1

我只添加到之前,你仍然可以使用cumsum實現這一偉大的答案:

import numpy as np 

def moving_average(a, n=5): 
    ret = np.cumsum(a.filled(0)) 
    ret[n:] = ret[n:] - ret[:-n] 
    counts = np.cumsum(~a.mask) 
    counts[n:] = counts[n:] - counts[:-n] 
    ret[~a.mask] /= counts[~a.mask] 
    ret[a.mask] = np.nan 

    return ret 

x = np.array([1.,3,np.nan,7,8,1,2,4,np.nan,np.nan,4,4,np.nan,1,3,6,3]) 
mx = np.ma.masked_array(x,np.isnan(x)) 
y = moving_average(mx) 
0

您可以創建一個臨時數組,並使用np.nanmean()(新的1.8版本,如果我沒有記錯):

import numpy as np 
temp = np.vstack([x[i:-(5-i)] for i in range(5)]) # stacks vertically the strided arrays 
means = np.nanmean(temp, axis=0) 

,並把原南放回原處與means[np.isnan(x[:-5])] = np.nan

然而,這看起來在存儲器方面(堆疊相同陣列跨越5次)和計算都是冗餘的。

+0

np.nanmean()不會返回'nan'任何地方在輸出數組中。 – krakenwagon

+0

@ krakenwagon,是的,你將它們添加回你的評論之前我編輯的行。 –

0

如果我理解正確,您想創建一個移動平均值,然後將結果元素填充爲nan,前提是這些元素的索引在原始數組中爲nan

import numpy as np 

>>> inc = 5 #the moving avg increment 

>>> x = np.array([1.,3,np.nan,7,8,1,2,4,np.nan,np.nan,4,4,np.nan,1,3,6,3]) 
>>> mov_avg = np.array([np.nanmean(x[idx:idx+inc]) for idx in range(len(x))]) 

# Determine indices in x that are nans 
>>> nan_idxs = np.where(np.isnan(x))[0] 

# Populate output array with nans 
>>> mov_avg[nan_idxs] = np.nan 
>>> mov_avg 
array([ 4.75, 4.75, nan, 4.4, 3.75, 2.33333333, 3.33333333, 4., nan, nan, 3., 3.5, nan, 3.25, 4., 4.5, 3.]) 
0

下面是一個使用步伐的方法 -

w = 5 # Window size 
n = x.strides[0]  
avgs = np.nanmean(np.lib.stride_tricks.as_strided(x, \ 
         shape=(x.size-w+1,w), strides=(n,n)),1) 

x_rem = np.append(x[-w+1:],np.full(w-1,np.nan)) 
avgs_rem = np.nanmean(np.lib.stride_tricks.as_strided(x_rem, \ 
           shape=(w-1,w), strides=(n,n)),1) 
avgs = np.append(avgs,avgs_rem)        
avgs[np.isnan(x)] = np.nan