背景及需求分析
现实生活中很多事件是隔三岔五的进行抽样采集,从而导致时间序列的不等间隔情况,时序的等间隔或不等间隔对时间序列分析至关重要,如何将这种不等间隔的时序通过某种变换转为等间隔的时序,通常会有插值和平移两种办法,我们以下面一个实例来解释插值和平移两种等间隔处理方法
origin TS
flight_date passenger_num
1201 2021-03-28 90
1202 2021-03-29 80
1203 2021-03-31 108
1204 2021-04-02 80
1205 2021-04-04 91
... ... ...
1265 2021-08-02 103
1266 2021-08-04 122
1267 2021-08-06 86
1268 2021-08-08 72
1269 2021-08-09 70
我们仔细看上面的时间序列数据,可以看到3月28日,3月29日两天连续采集,3月30日是没有采集的,同时4月1号也是没采集的,还有后面的8月7号也没有采集,这种既有时候连续每天,又有间隔的采集的就是典型的非等间隔时间序列。针对这种情况,我们先介绍插值法
插值
插值是指在间隔的时间点上通过插值技术手段将采集结果虚拟出来,如周五的观察值是100,周日的观察值是110,现在如果要给周六插上一个值的话,100-110都是可行的,比如这里取100和110的平均值进行插值,具体可以看下面过程
插值前
周五 100
周六 NaN
周日 110
插值后
周五 100
周六 105
周日 110
代码
def data_preprocess(data): #乘客人数时序数据预处理
airline_data = data[["flight_date", "passenger_num"]].sort_values(by="flight_date") #按日期排序
airline_data.drop_duplicates(subset= "flight_date", keep = "first", inplace =True) #按日期列去重
print("origin TS\n", airline_data)
plt.scatter(x=airline_data["flight_date"], y=airline_data["passenger_num"], color = 'r', label = "origin TS")
plt.xticks(fontsize=7,rotation=30)
plt.legend()
plt.show()
airline_data.set_index("flight_date", inplace = True) #重置索引,将flight_date设置为索引index
airline_data = airline_data.asfreq("D").interpolate(method="time") #设置频率和填充方法
plt.scatter(x=airline_data.index, y=airline_data["passenger_num"], color = 'b',label = "new TS")
plt.xticks(fontsize=7, rotation=30)
plt.legend()
plt.show()
print("new TS\n", airline_data)
ts = airline_data["passenger_num"] #乘客人数序列
return ts
效果预览
new TS
passenger_num
flight_date
2021-03-28 90.0
2021-03-29 80.0
2021-03-30 94.0
2021-03-31 108.0
2021-04-01 94.0
... ...
2021-08-05 104.0
2021-08-06 86.0
2021-08-07 79.0
2021-08-08 72.0
2021-08-09 70.0
插值的好处,各实际观测的绝对位置没有发生变化,插值后100这个观察值还是在周五,110观察值在周日,插值出来的周六的观察值是一个虚拟值,起到了调和的用处,如果前后两个实际观察值相差很大的话,这个虚拟值可供选择的范围就很大,不好确定,同时可以看到被插值的位置出现了密集的集中小范围趋势,这种往往会打破整体性的分布趋势,然后再来介绍平移法。
平移
平移是指在间隔的时间点上通过压缩和拉伸手段将采集结果偏置化出来到等间隔的,如周五的观察值是100,周日的观察值是110,现在将周五的观察值偏置一个单位到周六,那么周六的观察值为100,周日的观察值为110,具体可以看下面过程
平移前
![](/qrcode.jpg)
周五 100
周六 NaN
周日 110
平移后
周六 100
周日 110
代码
def data_preprocess(data): #乘客人数数据预处理
airline_data = data[["flight_date", "passenger_num"]].sort_values(by="flight_date") #按日期排序
airline_data.drop_duplicates(subset= "flight_date", keep = "first", inplace =True) #按日期列去重
print("origin TS\n", airline_data)
plt.scatter(x=airline_data["flight_date"], y=airline_data["passenger_num"], color = 'r', label = "origin TS")
plt.xticks(fontsize=7,rotation=30)
plt.legend()
plt.show()
airline_data["flight_date_"] = pd.date_range(start= str(list(airline_data["flight_date"])[-1]+datetime.timedelta(-len(airline_data)+1)), end = str(list(airline_data["flight_date"])[-1]), freq="D")
airline_data.set_index("flight_date_", inplace = True) #重置索引,将flight_date设置为索引index
airline_data = airline_data.asfreq("D") #设置频率
plt.scatter(x=airline_data.index, y=airline_data["passenger_num"], color = 'b',label = "new TS")
plt.xticks(fontsize=7, rotation=30)
plt.legend()
plt.show()
print("new TS\n", airline_data)
ts = airline_data["passenger_num"] #乘客人数序列
return ts
效果
new TS
flight_date passenger_num
flight_date_
2021-06-02 2021-03-28 90
2021-06-03 2021-03-29 80
2021-06-04 2021-03-31 108
2021-06-05 2021-04-02 80
2021-06-06 2021-04-04 91
... ... ...
2021-08-05 2021-08-02 103
2021-08-06 2021-08-04 122
2021-08-07 2021-08-06 86
2021-08-08 2021-08-08 72
2021-08-09 2021-08-09 70
效果预览
平移的好处,各实际观测的相对位置没有发生变化,平移后100这个观察值还是在110观察值的前一位,但是会丢掉其他信息,如本来在周五得到的观测值现在变成了周六的观察值,会丢掉时序差特性,同时,星期这个特征可能后续就用不上了。