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

Posted

技术标签:

【中文标题】通过使用 pandas 在时间序列中在先前的 NaN 之间分配值来回填值【英文标题】:Backfill values by distributing values across prior NaNs in a timeseries with pandas 【发布时间】:2018-10-19 15:04:56 【问题描述】:

我有一个时间序列,其中每个观察代表自上次观察以来某事物的总量,如果在该时间步中没有观察,则该值报告为 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

我已经尝试使用 pandas 的一些回填和插值方法来执行此操作,但没有找到完全符合我要求的方法。

【问题讨论】:

【参考方案1】:

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

np.bincountpd.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

替代的较短版本。这行得通,因为cumsum 自然地给了我factorize 的作用。

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

详情

在上面的两个选项中,我们需要确定空值在哪里,并在反向序列上使用cumsum 来定义组。在transform 选项中,我使用groupbysize 来计算这些组的大小。

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

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

【讨论】:

我很久以前从你的一篇文章中学到了 [::-1] 的把戏。我认为这是这个解决方案的关键。尤其是在考虑影响系列中“先前”值的问题时。【参考方案2】:

计算累积 NA,然后我们做update

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

以上是关于通过使用 pandas 在时间序列中在先前的 NaN 之间分配值来回填值的主要内容,如果未能解决你的问题,请参考以下文章

r 使用先前的非NA值填充NA行

在R中迭代地用先前的值填充NA行[重复]

如何在 python 中在 spark notebook 上使用 pandas(dashDB 上的数据)

pandas使用read_csv函数读取文件时指定数据列的数据类型pandas使用read_csv函数读取文件时通过keep_default_na参数设置缺失值替换为空字符串

在 debian10 中在不同的 python 版本上安装 pandas

在计算 Pandas 创建的数据框中的列的平均值时指定“跳过 NA”