时间序列数据是在不同或有规律的时间间隔内记录的一系列数据点或观察结果。一般来说,一个时间序列是以相等的时间间隔采取的数据点序列。记录数据点的频率可以是每小时、每天、每周、每月、每季度或每年。
时间序列预测是使用统计模型根据过去的结果来预测时间序列的未来值的过程。
时间序列分析包含了分析时间序列数据的统计方法。这些方法使我们能够提取有意义的统计数据、模式和数据的其他特征。时间序列在线形图的帮助下被可视化。因此,时间序列分析涉及了解时间序列数据的固有方面,以便我们能够创建有意义和准确的预测。
时间序列的应用被用于统计、金融或商业应用中。时间序列数据的一个非常常见的例子是纳斯达克或道琼斯等股票指数的每日收盘值。时间序列的其他常见应用是销售和需求预测,天气预测,计量经济学,信号处理,模式识别和地震预测。
在时间序列中,有各种术语和概念是我们应该知道的。这些术语和概念如下:- 1
import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
import matplotlib as mpl
import matplotlib.pyplot as plt # data visualization
import seaborn as sns # statistical data visualization
import os
for dirname, _, filenames in os.walk('data'):
for filename in filenames:
print(os.path.join(dirname, filename))
# You can write up to 5GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using "Save & Run All"
# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session
data/AirPassengers.csv
path = 'data/AirPassengers.csv'
df = pd.read_csv(path)
df.head()
Month | #Passengers | |
---|---|---|
0 | 1949-01 | 112 |
1 | 1949-02 | 118 |
2 | 1949-03 | 132 |
3 | 1949-04 | 129 |
4 | 1949-05 | 121 |
df.columns = ['Date','Number of Passengers']
df.head()
Date | Number of Passengers | |
---|---|---|
0 | 1949-01 | 112 |
1 | 1949-02 | 118 |
2 | 1949-03 | 132 |
3 | 1949-04 | 129 |
4 | 1949-05 | 121 |
def plot_df(df, x, y, title="", xlabel='Date', ylabel='Number of Passengers', dpi=100):
plt.figure(figsize=(15,4), dpi=dpi)
plt.plot(x, y, color='tab:red')
plt.gca().set(title=title, xlabel=xlabel, ylabel=ylabel)
plt.show()
plot_df(df, x=df['Date'], y=df['Number of Passengers'], title='Number of US Airline passengers from 1949 to 1960')
x = df['Date'].values
y1 = df['Number of Passengers'].values
# Plot
fig, ax = plt.subplots(1, 1, figsize=(16,5), dpi= 120)
plt.fill_between(x, y1=y1, y2=-y1, alpha=0.5, linewidth=2, color='seagreen')
plt.ylim(-800, 800)
plt.title('Air Passengers (Two Side View)', fontsize=16)
plt.hlines(y=0, xmin=np.min(df['Date']), xmax=np.max(df['Date']), linewidth=.5)
plt.show()
任何时间序列的可视化都可能由以下部分组成。基础水平+趋势+季节性+误差。
然而,并非所有时间序列都必须有趋势和/或季节性。一个时间序列可能没有一个明显的趋势,但有一个季节性,反之亦然。
def plot_df(df, x, y, title="", xlabel='Date', ylabel='Number of Passengers', dpi=100):
plt.figure(figsize=(15,4), dpi=dpi)
plt.plot(x, y, color='blue')
plt.gca().set(title=title, xlabel=xlabel, ylabel=ylabel)
plt.show()
plot_df(df, x=df['Date'], y=df['Number of Passengers'], title='Trend and Seasonality')
循环行为
如果这些模式不是基于固定日历的频率,那么它就是周期性的。因为,与季节性不同,周期性效应通常受到商业和其他社会经济因素的影响。
我们可能有不同的趋势和季节性的组合。根据趋势和季节性的性质,一个时间序列可以被建模为加法或乘法时间序列。系列中的每个观测值可以表示为各组成部分的总和或乘积。
Additive time series:
Multiplicative Time Series:
时间序列的分解可以通过将该序列视为基数水平、趋势、季节性指数和残差项的加法或乘法组合来进行。
statsmodels中的 seasonal_decompose 方便地实现了这一点
from statsmodels.tsa.seasonal import seasonal_decompose
from dateutil.parser import parse
# Multiplicative Decomposition
multiplicative_decomposition = seasonal_decompose(df['Number of Passengers'], model='multiplicative', period=30)
# Additive Decomposition
additive_decomposition = seasonal_decompose(df['Number of Passengers'], model='additive', period=30)
# Plot
plt.rcParams.update({'figure.figsize': (16,12)})
multiplicative_decomposition.plot().suptitle('Multiplicative Decomposition', fontsize=16)
plt.tight_layout(rect=[0, 0.03, 1, 0.95])
additive_decomposition.plot().suptitle('Additive Decomposition', fontsize=16)
plt.tight_layout(rect=[0, 0.03, 1, 0.95])
plt.show()
而乘法分解,看起来相当随机,这是好事。因此,在理想情况下,对于这个特定的系列,乘法分解应该是首选。
现在,我们将绘制一些平稳和非平稳时间序列的例子,以示清楚。
使数列平稳的最常用和最方便的方法是对数列至少进行一次差分,直到它变得近似平稳。
如果 Y t Y_t Yt是时间 t t t的值,那么 Y Y Y的第一个差值 Y = Y t − Y t − 1 Y=Yt-Y_{t-1} Y=Yt−Yt−1。更简单地说,序列的差分只是用当前值减去下一个值而已。
如果第一次差分不能使一个序列平稳,我们可以进行第二次差分,以此类推。
我们希望将非平稳序列转换成平稳序列的原因有很多。以下是这些原因。
+ 预测一个平稳序列相对容易,而且预测结果更可靠。
+ 一个重要的原因是,自回归预测模型本质上是线性回归模型,利用序列本身的滞后期作为预测因子。
一个系列的平稳性可以通过观察系列的图表来检查。
另一种方法是将该系列分成两个或更多的连续部分,并计算汇总统计数据,如平均值、方差和自相关。如果统计数字有很大差异,那么这个系列就不可能是静止的。
我们可以用几种定量的方法来确定一个给定的系列是否是平稳的。这可以通过称为单位根检验的统计检验来完成。
这种测试可以检查一个时间序列是否是非稳态的,是否拥有单位根。
单位根检验有多种实现方式,如:
Augmented Dickey Fuller test (ADF Test)
Kwiatkowski-Phillips-Schmidt-Shin – KPSS test (trend stationary)
Philips Perron test (PP Test)
扩增迪克-富勒检验或(ADF检验)是最常用的检测静止性的检验。在这里,我们假设无效假设是时间序列拥有单位根,是非平稳的。然后,我们收集证据来支持或拒绝无效假设。因此,如果我们发现ADF检验的p值小于显著性水平(0.05),我们就拒绝无效假设。
请随时查看以下链接,以了解更多关于ADF检验的信息:
https://en.wikipedia.org/wiki/Augmented_Dickey%E2%80%93Fuller_test
https://www.machinelearningplus.com/time-series/augmented-dickey-fuller-test/
https://machinelearningmastery.com/time-series-data-stationary-python/
http://www.insightsbot.com/augmented-dickey-fuller-test-in-python/
https://nwfsc-timeseries.github.io/atsa-labs/sec-boxjenkins-aug-dickey-fuller.html
https://www.statisticshowto.com/adf-augmented-dickey-fuller-test/
另一方面,KPSS检验是用来检验趋势的静止性。空白假设和P值的解释与ADH检验正好相反。
https://en.wikipedia.org/wiki/KPSS_test
https://www.machinelearningplus.com/time-series/kpss-test-for-stationarity/
https://www.statisticshowto.com/kpss-test/
https://nwfsc-timeseries.github.io/atsa-labs/sec-boxjenkins-kpss.html
Philips Perron或PP检验是一种单位根检验。在时间序列分析中,它被用来检验一个时间序列是1阶积分的无效假设。它是建立在上面讨论的ADF检验之上的。
关于PP检验的更多信息,请访问以下链接:
https://en.wikipedia.org/wiki/Phillips%E2%80%93Perron_test
https://www.mathworks.com/help/econ/pptest.html
https://people.bath.ac.uk/hssjrh/Phillips%20Perron.pdf
https://www.stata.com/manuals13/tspperron.pdf
与平稳序列一样,白噪声也不是时间的函数。因此,它的平均值和方差不随时间变化。但不同的是,白噪声是完全随机的,平均数为0,在白噪声中没有模式。
在数学上,一个平均数为0的完全随机的数字序列就是白噪声。
rand_numbers = np.random.randn(1000)
pd.Series(rand_numbers).plot(title='Random White Noise', color='b')
1.从时间序列中减去最佳拟合线。最佳拟合线可以从以时间步骤为预测因素的线性回归模型中获得。对于更复杂的趋势,我们可能希望在模型中使用二次项(x^2)。
2.我们减去从时间序列分解中得到的趋势成分。
3.减去平均值。
4.应用像Baxter-King滤波器(statsmodels.tsa.filters.bkfilter)或Hodrick-Prescott滤波器(statsmodels.tsa.filters.hpfilter)的滤波器来去除移动平均趋势线或周期成分。
现在,我们将实现前两种方法来解读时间序列。
# Using scipy: Subtract the line of best fit
from scipy import signal
detrended = signal.detrend(df['Number of Passengers'].values)
plt.plot(detrended)
plt.title('Air Passengers detrended by subtracting the least squares fit', fontsize=16)
Text(0.5, 1.0, 'Air Passengers detrended by subtracting the least squares fit')
# Using statmodels: Subtracting the Trend Component
from statsmodels.tsa.seasonal import seasonal_decompose
result_mul = seasonal_decompose(df['Number of Passengers'], model='multiplicative', period=30)
detrended = df['Number of Passengers'].values - result_mul.trend
plt.plot(detrended)
plt.title('Air Passengers detrended by subtracting the trend component', fontsize=16)
Text(0.5, 1.0, 'Air Passengers detrended by subtracting the trend component')
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A1b9ldwF-1669094635815)(output_35_1.png)]
有多种方法可以对时间序列进行去季候性处理。这些方法列举如下:
如果除以季节性指数效果不好,我们将对系列进行对数,然后进行去季节性处理。以后我们将通过取指数来恢复到原来的规模。
# Subtracting the Trend Component
# Time Series Decomposition
result_mul = seasonal_decompose(df['Number of Passengers'], model='multiplicative', period=30)
# Deseasonalize
deseasonalized = df['Number of Passengers'].values / result_mul.seasonal
# Plot
plt.plot(deseasonalized)
plt.title('Air Passengers Deseasonalized', fontsize=16)
plt.plot()
[]
检验一个时间序列的季节性的常用方法是绘制该序列,并检查固定时间间隔内的可重复模式。因此,季节性的类型是由时钟或日历决定的。
然而,如果我们想对季节性进行更明确的检查,可以使用自相关函数(ACF)图。有一个强烈的季节性模式,ACF图通常揭示了在季节性窗口的倍数上有明确的重复峰值。
# Test for seasonality
from pandas.plotting import autocorrelation_plot
# Draw Plot
plt.rcParams.update({'figure.figsize':(10,6), 'figure.dpi':120})
autocorrelation_plot(df['Number of Passengers'].tolist())
from statsmodels.tsa.stattools import acf, pacf
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
# Draw Plot
fig, axes = plt.subplots(1,2,figsize=(16,3), dpi= 100)
plot_acf(df['Number of Passengers'].tolist(), lags=50, ax=axes[0])
plot_pacf(df['Number of Passengers'].tolist(), lags=50, ax=axes[1])
/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/statsmodels/graphics/tsaplots.py:348: FutureWarning: The default method 'yw' can produce PACF values outside of the [-1,1] interval. After 0.13, the default will change tounadjusted Yule-Walker ('ywm'). You can use this method now by setting method='ywm'.
warnings.warn(
滞后图是一个时间序列与自身滞后的散点图。它通常被用来检查自相关。如果系列中存在任何模式,该系列是自相关的。如果没有这种模式,该系列可能是随机白噪声。
from pandas.plotting import lag_plot
plt.rcParams.update({'ytick.left' : False, 'axes.titlepad':10})
# Plot
fig, axes = plt.subplots(1, 4, figsize=(10,3), sharex=True, sharey=True, dpi=100)
for i, ax in enumerate(axes.flatten()[:4]):
lag_plot(df['Number of Passengers'], lag=i+1, ax=ax, c='firebrick')
ax.set_title('Lag ' + str(i+1))
fig.suptitle('Lag Plots of Air Passengers', y=1.05)
plt.show()
from statsmodels.tsa.stattools import grangercausalitytests
data = pd.read_csv('data/AirPassengers.csv')
data.columns = ['date','value']
data.head()
data['date'] = pd.to_datetime(data['date'])
data['month'] = data.date.dt.month
grangercausalitytests(data[['value', 'month']], maxlag=2)
Granger Causality
number of lags (no zero) 1
ssr based F test: F=7.4080 , p=0.0073 , df_denom=140, df_num=1
ssr based chi2 test: chi2=7.5667 , p=0.0059 , df=1
likelihood ratio test: chi2=7.3733 , p=0.0066 , df=1
parameter F test: F=7.4080 , p=0.0073 , df_denom=140, df_num=1
Granger Causality
number of lags (no zero) 2
ssr based F test: F=4.9761 , p=0.0082 , df_denom=137, df_num=2
ssr based chi2 test: chi2=10.3154 , p=0.0058 , df=2
likelihood ratio test: chi2=9.9579 , p=0.0069 , df=2
parameter F test: F=4.9761 , p=0.0082 , df_denom=137, df_num=2
{1: ({'ssr_ftest': (7.407967762077246, 0.007318844731632684, 140.0, 1),
'ssr_chi2test': (7.566709928407473, 0.005945621865036116, 1),
'lrtest': (7.373310381387228, 0.00661989587473731, 1),
'params_ftest': (7.4079677620772815, 0.007318844731632552, 140.0, 1.0)},
[,
,
array([[0., 1., 0.]])]),
2: ({'ssr_ftest': (4.976083922906437, 0.008199795902675753, 137.0, 2),
'ssr_chi2test': (10.315385650404584, 0.005754962083917427, 2),
'lrtest': (9.957923125859452, 0.006881204546490603, 2),
'params_ftest': (4.976083922906381, 0.008199795902676155, 137.0, 2.0)},
[,
,
array([[0., 0., 1., 0., 0.],
[0., 0., 0., 1., 0.]])])}
时间序列的平滑化在以下情况下可能是有用的。
我们可以用以下方法使时间序列平滑化。