2012-10-24 17 views
9

szukam zwięzły sposób przejść od:NumPy cumSum rozważa Koncepcja nieliczby

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

do:

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

Najlepsze, co mogę zrobić w sklepie jest:

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

Czy istnieje krótszy sposób na osiągnięcie tego samego? A co z wykonaniem sumy wzdłuż osi tablicy 2D?

+0

numpy ma 'funkcję nancumsum' dodany w wersji 1.12.0. Nie całkiem robi to, co chcesz bezpośrednio, ponieważ dałoby to wynik '[1, 5, 6, 6, 8, 8]'. –

Odpowiedz

5

Jak o (dla niezbyt dużych tablic):

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 są tylko dla tego typu sytuacji.

>>> 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 jest budować bibliotekę na szczycie numpy. To Series klasa ma cumsum metodę, która pozwala zachować nan i została znacznie szybciej niż rozwiązania zaproponowanego przez DSM:

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

Z tym, że nie pracuję z Pandami. – Benjamin