Python 通过在时间序列中跨先前的NAN分布值来回填值

Python 通过在时间序列中跨先前的NAN分布值来回填值,python,pandas,dataframe,time-series,interpolation,Python,Pandas,Dataframe,Time Series,Interpolation,我有一个时间序列,其中每个观察值表示自上次观察以来的总数量,如果该时间段中没有观察值,则该值报告为NaN。格式示例: Timestep Value 1 10 2 NaN 3 NaN 4 9 5 NaN 6 NaN 7 NaN 8 16 9 NaN 10 NaN 我想做的是在它之前将观察到的值分布在NAN上。例如,像[

我有一个时间序列,其中每个观察值表示自上次观察以来的总数量,如果该时间段中没有观察值,则该值报告为NaN。格式示例:

Timestep  Value
1          10
2          NaN
3          NaN
4          9
5          NaN
6          NaN
7          NaN
8          16
9          NaN
10         NaN
我想做的是在它之前将观察到的值分布在NAN上。例如,像[5,NaN,NaN,6]这样的序列将变成[5,2,2,2],最终观测值6分布在最后2个NaN值上。应用于数据帧的期望输出为:

Timestep  Value
1          10
2          3
3          3
4          3
5          4
6          4
7          4
8          4
9          NaN
10         NaN
我尝试过使用一些填充和插值方法来实现这一点,但没有找到任何符合我要求的方法。

transform

np.bincount
pd.factorize
其他较短的版本。这是因为
cumsum
自然而然地提供了
factorize
的功能

a = df.Value.notna().values[::-1].cumsum()[::-1]
df.Value.bfill().div(np.bincount(a)[a])

细节 在上面的两个选项中,我们需要确定空值的位置,并在反转序列上使用
cumsum
来定义组。在
transform
选项中,我使用
groupby
size
来计算这些组的大小

第二个选项使用箱子计数和切片来获得相同的序列

感谢@ScottBoston提醒我提及反向元素
[::-1]
计算累积NA,然后我们进行
更新

s=df.Value.notnull().cumsum().shift(1)
df.Value.update(df.Value.bfill()/s.groupby(s).transform('count'))
df
Out[885]: 
   Timestep  Value
0         1   10.0
1         2    3.0
2         3    3.0
3         4    3.0
4         5    4.0
5         6    4.0
6         7    4.0
7         8    4.0
8         9    NaN
9        10    NaN

很久以前,我从你的一篇博文中学到了[:-1]诀窍。我认为这是解决这个问题的关键。特别是,当考虑影响序列中“先验”值的问题时,这个方法也不错。我喜欢轮班+1.
a = df.Value.notna().values[::-1].cumsum()[::-1]
df.Value.bfill().div(np.bincount(a)[a])
s=df.Value.notnull().cumsum().shift(1)
df.Value.update(df.Value.bfill()/s.groupby(s).transform('count'))
df
Out[885]: 
   Timestep  Value
0         1   10.0
1         2    3.0
2         3    3.0
3         4    3.0
4         5    4.0
5         6    4.0
6         7    4.0
7         8    4.0
8         9    NaN
9        10    NaN