时间序列分析属于统计学的一个分支,涉及对有序的、通常是时间性的数据进行研究。当适当应用时,时间序列分析可以揭示意想不到的趋势,提取有用的统计数据,甚至预测未来的趋势。因此,它被应用于许多领域,包括经济学、天气预报和容量规划等。
在本教程中,我们将介绍时间序列分析中使用的一些常见技术,并逐步介绍操作、可视化时间序列数据所需的迭代步骤。
本指南将介绍如何在本地桌面或远程服务器上进行时间序列分析。处理大型数据集可能会占用大量内存,因此在任何情况下,计算机都需要至少2GB的内存来执行本指南中的一些计算。
在本教程中,我们将使用Jupyter Notebook来处理数据。如果您尚未安装,请按照我们的教程安装和设置Python 3的Jupyter Notebook。
我们将利用pandas
库,它在处理数据时提供了很大的灵活性,以及statsmodels
库,它允许我们在Python中进行统计计算。这两个库的结合扩展了Python的功能,显著增加了我们的分析工具包。
与其他Python软件包一样,我们可以使用pip
安装pandas
和statsmodels
。首先,让我们进入本地编程环境或基于服务器的编程环境:
cd environments
. my_env/bin/activate
从这里开始,让我们为我们的项目创建一个新目录。我们将其命名为timeseries
,然后进入该目录。如果您将项目命名为其他名称,请确保在整个指南中用您的名称替换timeseries
。
mkdir timeseries
cd timeseries
现在,我们可以安装pandas
、statsmodels
和数据绘图包matplotlib
。它们的依赖项也将被安装:
pip install pandas statsmodels matplotlib
到目前为止,我们已经准备好开始使用pandas
和statsmodels
进行工作。
要开始处理我们的数据,我们将启动Jupyter Notebook:
jupyter notebook
要创建一个新的笔记本文件,请从右上角的下拉菜单中选择New > Python 3:
!创建一个新的Python 3笔记本
这将打开一个笔记本,允许我们加载所需的库(请注意,我们使用了标准的缩写来引用pandas
、matplotlib
和statsmodels
)。在我们的笔记本顶部,我们应该写入以下内容:
import pandas as pd
import statsmodels.api as sm
import matplotlib.pyplot as plt
在本教程的每个代码块之后,您应该键入ALT + ENTER
来运行代码,并在笔记本中进入新的代码块。
方便的是,statsmodels
自带内置数据集,因此我们可以直接将时间序列数据集加载到内存中。
我们将使用一个名为“夏威夷火奴鲁鲁马努阿罗观测站连续空气样本中的大气二氧化碳(CO2)”的数据集,该数据集从1958年3月到2001年12月收集了CO2样本。我们可以这样导入这些数据:
data = sm.datasets.co2.load_pandas()
co2 = data.data
让我们看看我们的时间序列数据的前5行是什么样子:
print(co2.head(5))
co2
1958-03-29 316.1
1958-04-05 317.3
1958-04-12 317.6
1958-04-19 317.5
1958-04-26 316.4
通过导入包并准备好CO2数据集,我们可以继续对数据进行索引。
您可能已经注意到日期已经被设置为我们pandas
DataFrame的索引。在Python中处理时间序列数据时,我们应该确保使用日期作为索引,因此请务必始终检查,我们可以通过运行以下命令来实现:
co2.index
DatetimeIndex(['1958-03-29', '1958-04-05', '1958-04-12', '1958-04-19',
'1958-04-26', '1958-05-03', '1958-05-10', '1958-05-17',
'1958-05-24', '1958-05-31',
...
'2001-10-27', '2001-11-03', '2001-11-10', '2001-11-17',
'2001-11-24', '2001-12-01', '2001-12-08', '2001-12-15',
'2001-12-22', '2001-12-29'],
dtype='datetime64[ns]', length=2284, freq='W-SAT')
dtype=datetime[ns]
字段确认了我们的索引由日期时间戳对象组成,而length=2284
和freq='W-SAT'
告诉我们,我们有2284个每周日期时间戳,从星期六开始。
每周数据可能很难处理,因此让我们改为使用时间序列的月均值。这可以通过使用方便的resample
函数来实现,该函数允许我们将时间序列分组为桶(1个月),在每个组上应用函数(均值),并组合结果(每组一行)。
y = co2['co2'].resample('MS').mean()
在这里,术语MS
表示我们按月份将数据分组到桶中,并确保我们使用每个月的开始作为时间戳:
y.head(5)
1958-03-01 316.100
1958-04-01 317.200
1958-05-01 317.120
1958-06-01 315.800
1958-07-01 315.625
Freq: MS, Name: co2, dtype: float64
pandas
的一个有趣特性是它能够处理日期时间戳索引,这使我们能够快速地切片我们的数据。例如,我们可以将数据集切片,仅检索1990
年之后的数据点:
y['1990':]
1990-01-01 353.650
1990-02-01 354.650
...
2001-11-01 369.375
2001-12-01 371.020
Freq: MS, Name: co2, dtype: float64
或者,我们可以将数据集切片,仅检索1995
年10月到1996
年10月之间的数据点:
y['1995-10-01':'1996-10-01']
1995-10-01 357.850
1995-11-01 359.475
1995-12-01 360.700
1996-01-01 362.025
1996-02-01 363.175
1996-03-01 364.060
1996-04-01 364.700
1996-05-01 365.325
1996-06-01 364.880
1996-07-01 363.475
1996-08-01 361.320
1996-09-01 359.400
1996-10-01 359.625
Freq: MS, Name: co2, dtype: float64
通过适当地为处理时间数据进行索引,我们可以继续处理可能缺失的值。
现实世界的数据往往是杂乱的。正如我们从图中所看到的,时间序列数据中包含缺失值并不罕见。检查缺失值的最简单方法要么是直接绘制数据,要么是使用下面的命令来查看输出中的缺失数据:
y.isnull().sum()
5
这个输出告诉我们,在我们的时间序列中有 5 个月的数据缺失。
通常情况下,如果缺失值不是太多,我们应该“填补”这些缺失值,以免数据中出现间断。我们可以使用 pandas
中的 fillna()
命令来实现这一点。为简单起见,我们可以使用时间序列中最接近的非空值来填补缺失值,尽管需要注意的是,有时滚动均值可能更可取。
y = y.fillna(y.bfill())
填补了缺失值之后,我们可以再次检查是否存在任何空值,以确保我们的操作成功:
y.isnull().sum()
0
经过这些操作之后,我们看到我们已经成功填补了时间序列中的所有缺失值。
在处理时间序列数据时,通过可视化可以揭示很多信息。一些需要注意的事项包括:
我们可以使用 pandas
对 matplotlib
API 的封装来显示数据集的图表:
y.plot(figsize=(15, 6))
plt.show()
!时间序列可视化图 1
当我们绘制数据时,一些明显的模式出现了。时间序列具有明显的季节性模式,以及总体上升的趋势。我们还可以使用一种称为时间序列分解的方法来可视化我们的数据。顾名思义,时间序列分解允许我们将时间序列分解为三个不同的组成部分:趋势、季节性和噪音。
幸运的是,statsmodels
提供了方便的 seasonal_decompose
函数来执行季节性分解。如果您有兴趣了解更多信息,可以在以下论文中找到其原始实现的参考资料:“STL: A Seasonal-Trend Decomposition Procedure Based on Loess.”
下面的脚本展示了如何在 Python 中执行时间序列季节性分解。默认情况下,seasonal_decompose
返回一个相对较小的图形,因此代码块的前两行确保输出图形足够大,以便我们进行可视化。
from pylab import rcParams
rcParams['figure.figsize'] = 11, 9
decomposition = sm.tsa.seasonal_decompose(y, model='additive')
fig = decomposition.plot()
plt.show()
!时间序列季节性-趋势分解可视化图 2
使用时间序列分解可以更容易地快速识别数据中的均值变化或变异性。上面的图表清楚地显示了数据的上升趋势,以及其年度季节性。这些可以用来理解我们时间序列的结构。时间序列分解背后的直觉很重要,因为许多预测方法都建立在这种结构化分解的概念之上,以生成预测。
如果您跟随本指南,现在您已经具备了在 Python 中可视化和操作时间序列数据的经验。
为了进一步提高您的技能,您可以加载另一个数据集,并重复本教程中的所有步骤。例如,您可以使用 pandas
库读取一个 CSV 文件,或者使用 statsmodels
库预先加载的 sunspots
数据集:data = sm.datasets.sunspots.load_pandas().data
。