2016-10-07 119 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