平滑已知下滑的时间序列的函数
我有一个关于互联网测量实验的结果,随着时间的推移,数据的变化情况如下图所示。我正在使用pandas进行时间序列分析。数据中有一些下降的部分,这是因为服务器出现了故障。我在寻找一些好的方法来平滑这些数据。
在一些比较简单的内置平滑函数中,pd.rolling_max()
提供了一个相对不错的估算。不过,它的估算值有点偏高。我也尝试自己写了一个平滑函数,当数据下降超过20%时,它会保留之前的值。这个方法也能提供一个相对不错的估算,但这个阈值是随意设定的。
def my_smooth(win, thresh = 0.80):
win = win.copy()
for i, val in enumerate(win):
if i > 1 and val < win[i-1] * thresh:
win[i] = win[i-1]
return win[-1]
ts = pd.rolling_apply(ts, 6, my_smooth)
我的问题是,针对这种特定特征的时间序列,还有没有更好的平滑函数?(也就是说,它是事件的计数,并且在特定时间的主要测量误差是大幅度的低估)。另外,我建议的平滑函数能否做得更合理或优化一下?
1 个回答
5
我想分享一下我是怎么解决这个问题的,希望对其他有兴趣的人有帮助。首先,在研究了很多平滑技术后,我最终决定不使用平滑,因为这样会改变数据。我选择了过滤掉10%的异常值,这在机器学习和信号处理里是个常见的方法。
在我们的情况下,异常值是指由于测量记录失败而导致的低测量值。检测异常值的方法有很多,其中一些比较流行的技术在NIST的工程统计手册中有提到。考虑到我的数据有明显的趋势,我选择了一种“中位数绝对偏差”的变体:将测量序列中的每个点与滚动中位数进行比较,计算差值,然后适当地选择一个截断点。
# 'data' are the weekly measurements, in a Pandas series
filtered = data.copy()
dm = pd.rolling_median(data, 9, center=True)
df = sorted(np.abs(data - dm).dropna(), reverse=True)
cutoff = df[len(df) // 10]
filtered[np.abs(data - dm) > cutoff] = np.nan