2016-12-14 4 views
5

У меня есть данные временных рядов в следующем формате, где значение указывает накопленную сумму с момента последней записи. То, что я хочу сделать, это «распространение», что накопленный объем за прошлые периоды, содержащие NaN, так что этот вход:Pandas идиоматический способ для заполнения fillna

s = pd.Series([0, 0, np.nan, np.nan, 75, np.nan, np.nan, np.nan, np.nan, 50], 
       pd.date_range(start="Jan 1 2016", end="Jan 10 2016", freq='D')) 

2016-01-01  0.0 
2016-01-02  0.0 
2016-01-03  NaN 
2016-01-04  NaN 
2016-01-05  75.0 
2016-01-06  NaN 
2016-01-07  NaN 
2016-01-08  NaN 
2016-01-09  NaN 
2016-01-10  50.0 

Становится этот выход:

2016-01-01  0.0 
2016-01-02  0.0 
2016-01-03 25.0 
2016-01-04 25.0 
2016-01-05 25.0 
2016-01-06 10.0 
2016-01-07 10.0 
2016-01-08 10.0 
2016-01-09 10.0 
2016-01-10 10.0 

Есть идиоматическое Панды способ сделать это а не просто делать цикл за данными? Я пробовал множество вещей, связанных с fillna, dropna, isnull, делая shift, чтобы проверить следующее значение и т. Д., Но я не вижу, как скомпоновать их.

+0

Интересный вопрос. Я не думаю, что есть встроенный способ, и, к сожалению, вам, возможно, придется закончить цикл. –

ответ

5

Это может работать для каждого куска отсутствующих значений, создать переменную группы с cumsum (от конца ряда), а затем выполнить сгруппированных среднюю операцию на каждой порции:

s.groupby(s.notnull()[::-1].cumsum()[::-1]).transform(lambda g: g[-1]/g.size) 

#2016-01-01  0.0 
#2016-01-02  0.0 
#2016-01-03 25.0 
#2016-01-04 25.0 
#2016-01-05 25.0 
#2016-01-06 10.0 
#2016-01-07 10.0 
#2016-01-08 10.0 
#2016-01-09 10.0 
#2016-01-10 10.0 
#Freq: D, dtype: float64 

Или другой вариант:

s.groupby(s.shift().notnull().cumsum()).transform(lambda g: g[-1]/g.size) 

#2016-01-01  0.0 
#2016-01-02  0.0 
#2016-01-03 25.0 
#2016-01-04 25.0 
#2016-01-05 25.0 
#2016-01-06 10.0 
#2016-01-07 10.0 
#2016-01-08 10.0 
#2016-01-09 10.0 
#2016-01-10 10.0 
#Freq: D, dtype: float64 
Смежные вопросы