2012-10-24 6 views
9

ich für eine prägnante Art und Weise suchen, um von:Numpy cumsum Berücksichtigung NaNs

a = numpy.array([1,4,1,numpy.nan,2,numpy.nan]) 

zu:

b = numpy.array([1,5,6,numpy.nan,8,numpy.nan]) 

Das Beste, was ich zur Zeit tun kann, ist:

b = numpy.insert(numpy.cumsum(a[numpy.isfinite(a)]), (numpy.argwhere(numpy.isnan(a)) - numpy.arange(len(numpy.argwhere(numpy.isnan(a))))), numpy.nan) 

Ist gibt es einen kürzeren Weg, um das Gleiche zu erreichen? Wie wäre es mit einem Cumsum entlang einer Achse eines 2D-Arrays?

+0

numpy hat eine' nancumsum' Funktion in Version 1.12.0 hinzugefügt. Es tut nicht ganz, was Sie direkt wollen, da es Ihnen das Ergebnis "[1, 5, 6, 6, 8, 8]" geben würde. –

Antwort

5

Wie wäre es (für nicht allzu große Arrays):

In [34]: import numpy as np 

In [35]: a = np.array([1,4,1,np.nan,2,np.nan]) 

In [36]: a*0 + np.nan_to_num(a).cumsum() 
Out[36]: array([ 1., 5., 6., nan, 8., nan]) 
5

Masked arrays sind nur für diese Art von Situation.

>>> import numpy as np 
>>> from numpy import ma 
>>> a = np.array([1,4,1,np.nan,2,np.nan]) 
>>> b = ma.masked_array(a,mask = (np.isnan(a) | np.isinf(a))) 
>>> b 
masked_array(data = [1.0 4.0 1.0 -- 2.0 --], 
     mask = [False False False True False True], 
    fill_value = 1e+20) 
>>> c = b.cumsum() 
>>> c 
masked_array(data = [1.0 5.0 6.0 -- 8.0 --], 
     mask = [False False False True False True], 
    fill_value = 1e+20) 
>>> c.filled(np.nan) 
array([ 1., 5., 6., nan, 8., nan]) 
7

Pandas ist eine Bibliothek bauen oben auf numpy. Es ist Series Klasse eine cumsum Methode hat, die die nan ‚s bewahrt und ist wesentlich schneller als die Lösung von DSM vorgeschlagen:

In [15]: a = arange(10000.0) 

In [16]: a[1] = np.nan 

In [17]: %timeit a*0 + np.nan_to_num(a).cumsum() 
1000 loops, best of 3: 465 us per loop 

In [18] s = pd.Series(a) 

In [19]: s.cumsum() 
Out[19]: 
0  0 
1  NaN 
2  2 
3  5 
... 
9996 49965005 
9997 49975002 
9998 49985000 
9999 49994999 
Length: 10000 

In [20]: %timeit s.cumsum() 
10000 loops, best of 3: 175 us per loop 
+0

Außer, ich arbeite nicht mit Pandas. – Benjamin