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

时间:2019-05-13 00:38:32

标签: python pandas numpy time-series data-science

我的一般问题是我有一个数据框,其中的列与要素值相对应。数据框中还有一个日期列。每个功能列可能缺少NaN值。我想用诸如“ fill_mean”或“ fill zero”的填充逻辑填充一列。

但是我不想只将填充逻辑应用于整个列,因为如果较早的值之一是NaN,我不希望此特定NaN的平均值i会被后来的平均值所污染在什么时候该模型应该不了解。从本质上讲,这是不向模型泄漏有关未来信息的普遍问题,特别是在尝试填充我的时间序列时。

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

#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索引值。

1 个答案:

答案 0 :(得分:2)

如果要用熊猫系列nan上的滚动平均值(全窗口)替换s值,请注意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-2的数组n中插入最多O(n)个缺失项-但是它应该进行充分的优化(通过避免在本机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