我的一般问题是我有一个数据框,其中的列与要素值相对应。数据框中还有一个日期列。每个功能列可能缺少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索引值。
答案 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
来改善这一点。
时间复杂度
这不是log
或constant
时间,因为您必须从长度为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
。