前言
最近在对时序数据进行数据分析时,发现原始数据中存在异常低值,表现为在一段较平稳序列中突然出现一个数值较小的异常值,且该异常值明显低于附近值(相差十几倍)。由于数据量较多,人工识别此类异常值费时费力,因此通过查阅相关文献、博客对其进行检测与插补处理,以提高后期预测模型的精度。
原始数据:数据
链接:https://pan.baidu.com/s/1XXTfPuKlB55z0S8yQJJ0Nw
提取码:wing
表格:
画图显示
一、 savgol_filter滤波
基本知识: 参考网址savgol_filter滤波简介
- Savitzky-Golay滤波器最初由Savitzky和Golay于1964年提出。广泛地运用于数据流平滑除噪,是一种在时域内基于局域多项式最小二乘法拟合的滤波方法。这种滤波器最大的特点在于在滤除噪声的同时可以确保信号的形状、宽度不变。
- 它对信号的操作是在时域内对window_length内的数据进行多项式拟合。而从频域上看,这种拟合实际就是通过了低频数据,而滤掉了高频数据。
- 这种滤波其实是一种移动窗口的加权平均算法,但是其加权系数不是简单的常数窗口,而是通过在滑动窗口内对给定高阶多项式的最小二乘拟合得出。
代码:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from scipy.signal import savgol_filter
data_wsxg = pd.read_csv('Wanshouxigong_IDW_Linear.csv')
print(data_wsxg.head())
data_wsxg.insert(5, 'PM2.5_SG', np.nan)
"""1. savgol_filter滤波: 会出现负值, 且没有异常低值检测(人为识别)"""
# savgol_filter(data, window_length, polyorder) window_length(取奇数整数): 越大曲线越平滑; polyorder: 多项式拟合的阶数, 越大越更贴近原始曲线
data_wsxg['PM2.5_SG'] = savgol_filter(data_wsxg['PM2.5'], 7, 3)
print(data_wsxg.head())
data_wsxg.to_csv('Wanshouxigong_savgol_filter.csv', index=None)
plt.plot(data_wsxg['PM2.5'][200:400], color='black', label='PM2.5_true')
plt.plot(data_wsxg['PM2.5_SG'][200:400], color='red', linestyle='--', label='PM2.5_SG')
plt.legend()
plt.show()
注意: window_length的值必须为正奇整数,不然程序会报错。
结果:
计算原始序列与趋势序列在各个时刻的偏差比率
d
ratio
(
t
)
=
∣
x
t
−
tend
t
∣
x
t
d_{\text {ratio }(t)}=\frac{\mid x_{t}-\text { tend }_{t} \mid}{x_{t}}
dratio (t)=xt∣xt− tend t∣
设置偏差比率的阈值,将偏差比率大于阈值的时刻判定为异常低值。根据数据分析情况,将偏差阈值设置为5。可得经过滤波校正后的数据:
滤波后的结果:
总结:方法较简单,运行效率快;缺点是滤波结果会出现负值, 这明显与PM2.5监测数据矛盾,且无异常低值检测(只能通过自定义去判断)。