4. 数据可视化与探索:Matplotlib/Seaborn绘制时间序列图、ACF/PACF图解读
数据可视化,说白了就是让数据开口说话。你想想看,一堆数字摆在那,你很难看出门道。但画成图,趋势、周期、异常点,一眼就能揪出来。
我个人习惯,拿到时间序列数据后,第一件事不是跑模型,而是画图。先看原始序列图,再看自相关和偏自相关图。这三张图,基本能告诉你80%的信息。
4.1 原始时间序列图:第一印象
原始序列图,就是把时间作为横轴,数值作为纵轴,把点连成线。这是最基础,也是最直观的图。
我建议你用Matplotlib来画。它灵活,可控性强。Seaborn虽然好看,但有时候自定义起来反而麻烦。
import matplotlib.pyplot as plt
import pandas as pd
# 假设你有一个DataFrame,索引是时间
df = pd.read_csv('sales_data.csv', parse_dates=['date'], index_col='date')
plt.figure(figsize=(12, 5))
plt.plot(df.index, df['sales'], color='#2E86AB', linewidth=1.5)
plt.title('每日销售额时间序列', fontsize=14)
plt.xlabel('日期')
plt.ylabel('销售额(元)')
plt.grid(True, alpha=0.3)
plt.show()
嗯,这里要注意:时间索引一定要是datetime类型。我遇到过好几次,有人把日期当字符串传进去,结果横轴乱序,图完全没法看。
看原始序列图,重点看什么?
- 趋势:整体是上升、下降,还是平稳?
- 季节性:有没有明显的周期性波动?比如每年夏天销量高,冬天低。
- 异常点:有没有突然的尖峰或低谷?可能是数据错误,也可能是突发事件。
- 方差变化:波动幅度是否随时间变化?如果波动越来越大,可能需要做对数变换。
我的小技巧:如果数据点太多(比如每分钟一条),画出来会密密麻麻。这时候可以先用resample()降采样,比如按天或按周聚合,再看整体趋势。
4.2 ACF与PACF:揭开时间依赖的面纱
原始序列图看的是「值」的变化。但时间序列分析的核心,是看「值之间的关系」。具体来说,就是当前时刻的值,跟过去哪些时刻的值有关。
这时候就要请出ACF(自相关函数)和PACF(偏自相关函数)了。
4.2.1 ACF图:看总体的相关性
ACF衡量的是:当前时刻的值,与滞后k期的值之间的相关性。注意,这里包含间接影响。比如,t时刻与t-2时刻的相关性,可能有一部分是通过t-1时刻传递过去的。
我用Seaborn画ACF图,因为它默认带置信区间,方便判断相关性是否显著。
from statsmodels.graphics.tsaplots import plot_acf
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 4))
plot_acf(df['sales'], lags=30, alpha=0.05)
plt.title('销售额的ACF图')
plt.xlabel('滞后阶数')
plt.ylabel('自相关系数')
plt.show()
ACF图怎么看?
- 如果ACF在滞后几阶后迅速衰减到0附近,说明序列可能是平稳的。
- 如果ACF衰减很慢,拖尾很长,说明序列可能有趋势或非平稳性。
- 如果ACF在某个滞后阶数上突然跳出置信区间,说明那个滞后阶数有显著相关性。
我曾经踩过的坑:有一次,我看到ACF图在滞后12阶处有个很高的尖峰,以为模型需要包含12阶滞后。后来才发现,数据是月度数据,那个尖峰只是季节性周期。所以,一定要结合业务背景看ACF,别光看统计显著性。
4.2.2 PACF图:看直接的相关性
PACF剔除了中间变量的影响,只保留「直接」的相关性。比如,PACF在滞后2阶处显著,说明t时刻与t-2时刻有直接关系,而不是通过t-1传递的。
from statsmodels.graphics.tsaplots import plot_pacf
plt.figure(figsize=(10, 4))
plot_pacf(df['sales'], lags=30, alpha=0.05, method='ywm')
plt.title('销售额的PACF图')
plt.xlabel('滞后阶数')
plt.ylabel('偏自相关系数')
plt.show()
PACF图怎么看?
- 如果PACF在p阶后截尾(突然降到0附近),说明AR模型的阶数可能是p。
- 如果PACF拖尾,说明可能更适合用MA模型。
ACF与PACF的经典组合判断:
| 模型 | ACF | PACF |
|---|---|---|
| AR(p) | 拖尾(逐渐衰减) | p阶后截尾 |
| MA(q) | q阶后截尾 | 拖尾(逐渐衰减) |
| ARMA(p,q) | 拖尾 | 拖尾 |
4.3 用Seaborn画更漂亮的图
Matplotlib是基础,但Seaborn能让图更好看,尤其适合做探索性分析时快速出图。
import seaborn as sns
# 设置Seaborn风格
sns.set_style('whitegrid')
sns.set_palette('husl')
# 画原始序列图
plt.figure(figsize=(12, 5))
sns.lineplot(data=df, x=df.index, y='sales')
plt.title('销售额时间序列 (Seaborn版)')
plt.show()
我个人习惯,正式报告用Seaborn,因为配色和样式更专业。但调试模型时,我还是用Matplotlib,因为改起来快。
4.4 本章知识体系
下面这张图,帮你理清数据可视化与探索的核心逻辑:
4.5 实战中的避坑指南
讲完理论,说点实战中容易踩的坑。
避坑1:别只看ACF/PACF的绝对值
有一次,我看到ACF在滞后1阶处是0.3,觉得相关性不高。但后来发现,样本量很大(10000个点),0.3已经非常显著了。记住:显著性要看置信区间,不是看数值大小。
避坑2:差分后的ACF/PACF会变
我曾经对非平稳序列做了一阶差分,然后看ACF。结果发现ACF在滞后1阶处变成了负值,而且很显著。当时我以为是数据有问题,后来才明白:差分本身会引入负的自相关,这是正常的。
避坑3:季节性数据要画季节图
如果你有月度数据,我建议你画一个「按月份分组的箱线图」。这样能直观看到,每年哪个月份高,哪个月份低。ACF图虽然也能看出季节性,但不如箱线图直观。
# 画季节箱线图
df['month'] = df.index.month
sns.boxplot(data=df, x='month', y='sales')
plt.title('各月份销售额分布')
plt.show()
好了,数据可视化这块就讲这么多。记住:图是给你自己看的,不是给别人看的。画图的目的,是帮你理解数据,而不是为了好看。所以,怎么有效怎么来。
公众号:蓝海资料掘金营,微信deep3321