如何有效地填充时间序列?

Posted

技术标签:

【中文标题】如何有效地填充时间序列?【英文标题】:How to efficiently fill a time series? 【发布时间】:2019-09-29 22:59:04 【问题描述】:

我的一般问题是我有一个数据框,其中列对应于特征值。数据框中还有一个日期列。每个特征列可能缺少 NaN 值。我想用一些填充逻辑填充一列,例如“fill_mean”或“填充零”。

但我不想只将填充逻辑应用于整个列,因为如果较早的值之一是 NaN,我不希望我为这个特定 NaN 填充的平均值被后来的平均值所污染on,什么时候模型应该不知道。本质上,这是一个常见问题,即不向您的模型泄露有关未来的信息 - 特别是在尝试填充我的时间序列时。

无论如何,我已将问题简化为几行代码。这是我对上述一般问题的简化尝试:

#assume ts_values is a time series where the first value in the list is the oldest value and the last value in the list is the most recent.
ts_values = [17.0, np.NaN, 12.0, np.NaN, 18.0]
nan_inds = np.argwhere(np.isnan(ts_values))
for nan_ind in nan_inds:
    nan_ind_value = nan_ind[0]
    ts_values[nan_ind_value] = np.mean(ts_values[0:nan_ind_value])

上述脚本的输出为:

[17.0, 17.0, 12.0, 15.333333333333334, 18.0]

这正是我所期望的。

我对此的唯一问题是,它与数据集中的 NaN 数量呈线性关系。有没有办法在我不迭代 nan 索引值的常量或日志时间内做到这一点。

【问题讨论】:

我认为没有循环是不行的,我们可以尝试使用numba来加快速度 【参考方案1】:

如果您想在熊猫系列s 上将nan 值替换为滚动平均值(全窗口),请注意WeNYoBen 在填充期间不会继续滚动平均值计算。 (所以你的 15.3 变成了 12.0)。

s.fillna(s.expanding(1).mean())

如果您希望在 nans 被填充时更新滚动平均值,这个就地 numba 解决方案可能会有所帮助

import numpy as np
import numba
from numba import jit


@jit(nopython=True)
def rolling_fill(a): 
    for i, e in enumerate(a):
        if np.isnan(e):
            a[i] = np.mean(a[:i])

ts_values = np.array([17.0, np.NaN, 12.0, np.NaN, 18.0])
rolling_fill(ts_values)
print(ts_values)

这给了

[17.         17.         12.         15.33333333 18.        ]

您可以通过保留总和而不是每次都调用.mean 来改善这一点。

时间复杂度

这不是logconstant 时间,因为您必须从长度为n 的数组中插入最多n-2 缺失的项目@ 987654336@ - 但它应该被充分优化(通过避免在本机 python) 并且您不能 理论上 做得更好,但是上述的较低级别的实现将使这大大加快。


编辑:我最初误读并认为您在询问插值

你想interpolate这个系列,熊猫直接支持这个。

>>> s = pd.Series([0, 1, np.nan, 5])
>>> s
0    0.0
1    1.0
2    NaN
3    5.0
dtype: float64
>>> s.interpolate()
0    0.0
1    1.0
2    3.0
3    5.0
dtype: float64

或者如果您不想使用pandas,因为您的示例是ndarray,那么请相应地使用numpy.interp

【讨论】:

请检查您的输出。 不错的捕获@WeNYoBen - 不知道如何在没有循环的情况下解决它。可能需要一些 jit

以上是关于如何有效地填充时间序列?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用python有效地填充“缺失时间模式”和“填充它们”具有特定值?

如何有效地填充字节数组

如何使用python有效地填充给定一个非常大的表的矩阵?

有没有办法用两个日期之间的每小时日期时间有效地填充 python 中的 pandas df 列?

如何有效地查看 TabNavigator 页面

使用 Mongoose 和 GraphQL 从填充模型有条件地返回值的最有效方法?