我的一般问题是,我有一个数据格式,其中列对应于特性值。在dataframe中也有一个日期列。每个功能列都可能缺少NaN值。我想用一些填充逻辑填充列,例如"fill_mean“或”填充零“。
但是,我不想仅仅将填充逻辑应用于整个列,因为如果前面的值之一是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])
以上脚本的输出如下:
[17.0, 17.0, 12.0, 15.333333333333334, 18.0]
这正是我所期望的。
我唯一的问题是,相对于数据集中的NaNs数,它将是线性时间。在不迭代nan索引值的情况下,是否有一种在常量或日志时间内这样做的方法。
发布于 2019-05-12 16:44:24
如果您希望将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
时间,因为您最多必须从长度为O(n)
的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
。
https://stackoverflow.com/questions/56104615
复制