1. 时间序列介绍
时间序列是指按固定时间间隔记录的一系列观测数据。根据观测频率的不同,时间序列通常可以是每小时、每天、每周、每月、每季度和每年。有时,也可能出现秒级和分钟级的时间序列,例如每分钟的点击次数和用户访问次数等。
2. 如何在Python中导入时间序列数据
时间序列数据通常以 .csv 文件或其他电子表格格式存储,包含两列:日期和测量值。 我们使用 pandas 包中的 read_csv() 函数将时间序列数据集(一个关于澳大利亚药品销售的 csv 文件)读取为 pandas 数据框。添加 parse_dates=[‘date’] 参数会将日期列解析为日期字段。
# 从dateutil包中导入parse函数,可以把把字符串日期(如 "2024-01-01")转换成日期时间格式from dateutil.parser import parse# 导入 matplotlib 主库,并命名为 mpl,matplotlib 是 Python 最常用的绘图库,mpl 常用于设置全局参数、颜色、字体等import matplotlib as mpl# 导入 pyplot 模块,并简写为 plt,pyplot类似R里面的plot()系统,用来画折线图、柱状图、散点图等import matplotlib.pyplot as plt# 导入seaborn,并简写为sns,seaborn基于matplotlib,画图更美观import seaborn as sns# 导入numpy,numpy用于数值计算、矩阵运算,类似R里面的向量/矩阵基础库import numpy as np# pandas 是处理表格数据最重要的库,类似 R 的 data.frame + dplyr + readr 综合体import pandas as pd# 设置matplotlib全局绘图参数# 'figure.figsize': (10,7)plt.rcParams.update({'figure.figsize': (10,7), 'figure.dpi': 120})# 读取当前数据,parse_dates=['date']表示把这一列自动识别为日期格式# 数据来源:https://raw.githubusercontent.com/selva86/datasets/master/a10.csvdf = pd.read_csv('project_1.csv', parse_dates=['date'])# 查看数据前5行df.head()
面板数据也是基于时间的数据集。区别在于,除了时间序列之外,它还包含一个或多个在同意时间段内测量的相关变量。 通常情况下,面板数据中的列包含有助于预测Y的解释变量,前提是这些列在未来的预测期内可用。
# 面板数据示例# 数据来源: https://raw.githubusercontent.com/selva86/datasets/master/MarketArrivals.csv# 导入数据df = pd.read_csv('MarketArrivals.csv')# 从原始数据中筛选market列等于MUMBAI的行df = df.loc[df.market=='MUMBAI', :]df.head()
# 加载库import matplotlib.pyplot as plt# 数据来源:https://raw.githubusercontent.com/selva86/datasets/master/a10.csv# 导入数据df = pd.read_csv('project_1.csv', parse_dates=['date'])# 可视化# 定义一个函数plot_df用于快速绘图def plot_df(df, x, y, title = "", xlabel = 'Date', ylabel = 'Value', dpi = 300) :# 新建画布plt.figure(figsize = (16,8), dpi = dpi)# 绘制折线图,线条颜色为红色plt.plot(x, y, color = 'tab:red')# 获取当前坐标轴对象plt.gca() .set(title = title, xlabel = xlabel, ylabel = ylabel)# 显示图片plt.show()# 调用plot_df函数绘图plot_df(df, x = df.index, y = df.value,title = 'Monthly anti-diabetic drug sales in Australia from 1992 to 2008')

# 数据来源:https://raw.githubusercontent.com/selva86/datasets/master/a10.csv# 导入数据df = pd.read_csv('project_1.csv', parse_dates=["date"])# 重置行索引df.reset_index(inplace=True)# 准备数据df['year'] = [d.year for d in df.date] # 取出date列,提取年份,逐个历遍每个日期df['month'] = [d.strftime('%b') for d in df.date] # 提取月份years = df['year'].unique() # 提取year列中的所有唯一年份# 准备颜色# 设置随机种子数np.random.seed(100)# 随机选择颜色,replace=False表示不重复抽取颜色mycolors = np.random.choice(list(mpl.colors.XKCD_COLORS.keys()), len(years), replace=False)# 绘图plt.figure(figsize=(16,12), dpi= 80)for i, y in enumerate(years):if i > 0:plt.plot('month', 'value', data=df.loc[df.year==y, :], color=mycolors[i], label=y)plt.text(df.loc[df.year==y, :].shape[0]-.9, df.loc[df.year==y, 'value'][-1:].values[0], y, fontsize=12, color=mycolors[i])# 修饰图plt.gca().set(xlim=(-0.3, 11), ylim=(2, 30), ylabel='$Drug Sales$', xlabel='$Month$')plt.yticks(fontsize=12, alpha=.7)plt.title("Seasonal Plot of Drug Sales Time Series", fontsize=20)plt.show()

从上图可以看到,每年2月,药品销量都会大幅下降,三月又会回升,四月再次下降,如此循环往复。显然,这种模式每年都会出现。
然而,随着时间的推移,药品总销售额呈上升趋势。我们可以通过绘制年度箱线图来直观地展示这一趋势及其逐年变化情况。同样,可以通过绘制月度箱线图来可视化月度分布情况。
# 数据来源:https://raw.githubusercontent.com/selva86/datasets/master/a10.csv# 导入数据df = pd.read_csv('project_1.csv', parse_dates=['date'], index_col='date')# 重置行索引df.reset_index(inplace=True)# 准备数据df['year'] = [d.year for d in df.date]df['month'] = [d.strftime('%b') for d in df.date]years = df['year'].unique()# 绘图fig, axes = plt.subplots(1, 2, figsize=(20,7), dpi= 80)sns.boxplot(x='year', y='value', data=df, ax=axes[0], palette='Set3')sns.boxplot(x='month', y='value', data=df.loc[~df.year.isin([1991, 2008]), :], ax = axes[1], palette = 'Pastel1')# 设置标题axes[0].set_title('Year-wise Box Plot\n(The Trend)', fontsize=18);axes[1].set_title('Month-wise Box Plot\n(The Seasonality)', fontsize=18)plt.show()

5. 时间序列中的模式 (Patterns in a time series)
任何时间序列都可以分解为以下几个组成部分: 基准水平 + 趋势 + 季节性 + 误差。当时间序列中出现递增或递减的斜率时,即可观察到趋势。而当由于季节性因素导致在固定时间间隔内出现明显的重复模式时,即可观察到季节性。这种模式可能与一年中的月份、月份中的日期、星期几甚至一天中的时间有关。
然而,并非所有时间序列都必须具有趋势和/或季节性。一个时间序列可能没有明显的趋势,但具有季节性。反之亦然。因此,可以将时间序列想象成趋势、季节性和误差项的组合。
# 数据来源如下:# https://raw.githubusercontent.com/selva86/datasets/master/guinearice.csv# https://raw.githubusercontent.com/selva86/datasets/master/sunspotarea.csv# https://raw.githubusercontent.com/selva86/datasets/master/AirPassengers.csvfig, axes = plt.subplots(1,3, figsize=(20,4), dpi=100)pd.read_csv('guinearice.csv', parse_dates=['date'], index_col='date').plot(title='Trend Only', legend=False, ax=axes[0])pd.read_csv('sunspotarea.csv', parse_dates=['date'], index_col='date').plot(title='Seasonality Only', legend=False, ax=axes[1])pd.read_csv('AirPassengers.csv', parse_dates=['date'], index_col='date').plot(title='Trend and Seasonality', legend=False, ax=axes[2])

另一个需要考虑的方面是周期性行为。当序列的涨跌模式并非按照固定的日历周期发生时,就会出现周期性行为。需要注意的是,不要将“周期性”效应与“季节性”效应混淆。
那么,如何区分“周期性”模式和“季节性”模式呢?
如果这些模式并非基于固定的日历频率,那么它就是周期性的。因为与季节性不同,周期性影响通常受到商业和其他社会经济因素的影响。