通过在具有pandas的时间序列中的先前NaN之间分配值来回填值

the*_*ian 2 python interpolation time-series dataframe pandas

我有一个时间序列,其中每个观察值代表自上次观察以来的某些事物的总量,如果在该时间步长中没有观察到那么该值被报告为NaN.格式示例:

Timestep  Value
1          10
2          NaN
3          NaN
4          9
5          NaN
6          NaN
7          NaN
8          16
9          NaN
10         NaN
Run Code Online (Sandbox Code Playgroud)

我想做的是在它之前在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
Run Code Online (Sandbox Code Playgroud)

我试过用一些pandas回填和插值方法做这个,但没有找到任何我想要的东西.

piR*_*red 7

transform

df.Value.bfill().div(
    df.groupby(df.Value.notna()[::-1].cumsum()).Value.transform('size')
)

0    10.0
1     3.0
2     3.0
3     3.0
4     4.0
5     4.0
6     4.0
7     4.0
8     NaN
9     NaN
Name: Value, dtype: float64
Run Code Online (Sandbox Code Playgroud)

np.bincount 和 pd.factorize

a = df.Value.notna().values
f, u = pd.factorize(a[::-1].cumsum()[::-1])

df.Value.bfill().div(np.bincount(f)[f])

0    10.0
1     3.0
2     3.0
3     3.0
4     4.0
5     4.0
6     4.0
7     4.0
8     NaN
9     NaN
Name: Value, dtype: float64
Run Code Online (Sandbox Code Playgroud)

替代短版.这是有效的,因为cumsum自然给了我什么factorize.

a = df.Value.notna().values[::-1].cumsum()[::-1]
df.Value.bfill().div(np.bincount(a)[a])
Run Code Online (Sandbox Code Playgroud)

细节

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

第二个选项使用bin计数和切片来获得相同的系列.

谢谢@ScottBoston提醒我提到反转元素 [::-1]