som*_*ode 6 python numpy time-series pandas data-science
我的一般问题是我有一个数据框,其中的列与要素值相对应。数据框中还有一个日期列。每个功能列可能缺少NaN值。我想用诸如“ fill_mean”或“ fill zero”的填充逻辑填充一列。
但是我不想只将填充逻辑应用于整个列,因为如果较早的值之一是NaN,则我不希望此特定NaN的平均值被后来的平均值所污染。该模型应该没有任何知识。从本质上讲,这是不向模型泄漏有关未来信息的普遍问题,尤其是在尝试填充我的时间序列时。
无论如何,我已经将问题简化为几行代码。这是我对上述一般问题的简化尝试:
#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])
Run Code Online (Sandbox Code Playgroud)
上面脚本的输出是:
[17.0, 17.0, 12.0, 15.333333333333334, 18.0]
Run Code Online (Sandbox Code Playgroud)
这正是我所期望的。
我唯一的问题是,相对于数据集中NaN的数量,它将是线性时间。有没有办法在常量或日志时间内执行此操作,而我不会遍历nan索引值。
如果您希望将nanpandas 系列上的值替换为滚动平均值(全窗口)s,请注意WeNYoBen,这不会在填充期间继续滚动平均值计算。(所以你的 15.3 变成了 12.0)。
s.fillna(s.expanding(1).mean())
Run Code Online (Sandbox Code Playgroud)
如果您希望滚动平均值随着 nan 的填充而更新,这个就地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)
Run Code Online (Sandbox Code Playgroud)
这使
[17. 17. 12. 15.33333333 18. ]
Run Code Online (Sandbox Code Playgroud)
你也许可以通过保留一笔金额而不是.mean每次都打电话来改善这一点。
时间复杂度
这不是log时间,因为您必须从长度数组中constant插入最多缺失的项目 - 但它应该进行充分优化(通过避免本机 python 中的迭代),并且理论上您不能做得更好,但可以是上述内容的较低级别实现将使这变得更快。n-2nO(n)
编辑:我最初误读并认为你在问插值
你想要interpolate这个系列,pandas 直接支持这个。
>>> 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
Run Code Online (Sandbox Code Playgroud)
或者,如果您不想使用,pandas因为您的示例是 an ndarray,则相应地使用numpy.interp。