当前位置:   article > 正文

python对acf、pacf复现_import acf

import acf

介绍

代码、数据全部免费,都放在我的gitee仓库里面https://gitee.com/yuanzhoulvpi/time_series,想要使用的可以直接到我这个仓库下载。本文对应的jupyter notebook链接为:点击文章最后的【阅读原文】

本文是继python与时间序列(开篇)的第二篇,详细介绍了时间序列的两个重要的相关性系数:acf和pacf,本文将围绕着acf、pacf怎么算、怎么画来具体展开。

这也是你见到的第一篇详细介绍如何用python复现acf、pacf~

本文内容比较多【粗略统计:所有文本接近8000字;代码超过300行】。

图片

具体的jupyter notebook结构如下:

  1. 时间序列中最基本的概念;

  2. 什么叫lag(滞后);

  3. 时间序列的公式;

  4. 统计基础知识;

  5. 自相关系数(公式、复现、调包、可视化);

  6. 偏自相关系数(公式、复现、调包、可视化);

1.时间序列中最基本的概念

很多人看不懂时间序列的公式、很多人看不懂时间序列的数据、代码、数学函数。本文就是将数据、公式、代码、数学函数串联起来,让你不仅仅了解抽象的数学公式,也能将抽象的内容联系到具体的数据和python代码中,并且也不只是单纯的调用python包,而是自己手写算法。

下面的代码是近20年城镇就业人员数据(万人),数据来自中国统计局。

  1. import numpy as np
  2. import pandas as pd
  3. import datetime
  4. import matplotlib.pyplot as plt
  5. data = pd.read_csv("../datasets/近20年城镇就业人员数据(万人).csv"index_col=['year'])
  6. data.head(4)

图片

  1. # 可视化
  2. fig, ax = plt.subplots(figsize=(104))
  3. ax.plot(data.indexdata['value'], 'o-')
  4. ax.set_title(u"Data on urban employees in the past 20 years")
  5. ax.set_ylabel("Ten thousand people")
  6. ax.set_xlabel("year")
  7. ax.set_xticks(data.index)
  8. ax.set_xticklabels(data.index, rotation=45)

图片

2.什么叫lag(滞后)

经常在时间序列里面可以看到lag这个东西,大白话就是叫滞后;举个例子来说:

  1. lag1代表滞后数据1项,也就是2002年的数据滞后1年得到的就是2001年的数据;2003年的数据滞后1年就是2002年的数据;

  2. lag2代表滞后数据2项,也就是2003年的数据滞后2年得到2001年的数据;2004年的数据滞后2年就是2002年的数据;

  3. 依次类推,滞后数据就是这么计算的。

下面使用python对上面的【近20年城镇就业人员数据(万人)】数据做个滞后处理。

  1. # 使用pandas的shift可以做lag
  2. data1 = data.copy()
  3. data1['value_lag1'= data1['value'].shift(1)
  4. data1['value_lag2'=  data1['value'].shift(2)
  5. for i in [12345]:
  6.     data1[f"value_lag{i}"= data1['value'].shift(i)
  7. data1.head(10)

图片

数据解读:

  1. 因为2001年之前是没有数据了,所以2001年滞后一项得到的数据是空数据;

  2. 因为2002年之前是没有数据,所以2002年滞后两项也是没有数据的。

  3. 依次类推。

3.时间序列的公式

经常看到时间序列的公式写的乱七八糟的,这是一堆公式,那是一堆公式,活活把人绕晕。现在为了我们说明需要,我们定义几个简单的公式:

假设我们的时间序列是value = [4,3,2,10,3]。我们把这个时间序列定义为 ;那么这个时间序列里面每一个元素对应的符号依次是:、、等。

如果做了lag1,得到的时间序列为value lag1=[nan, 4,3,2,10],记这个新的时间序列为。

如果做了lag2,得到的时间序列为value lag2=[nan,nan, 4,3,2],记这个新的时间序列为。

以此类推,就是一个简单的时间序列公式了。

4.统计基础知识

  1. 均值:

  2. 方差:

  3. 协方差:

  4. 相关系数:

5.自相关系数

5.1自相关基础计算

在了解上面的【统计基础知识】后,再理解自相关性基本上就不难了,自相关是变量与自身在不同时间滞后下的相关性。对于延迟阶的时间序列。自协方差为,自相关性系数为

5.2调用包计算acf数值

  1. # 使用statsmodels包的acf函数
  2. from statsmodels.tsa.stattools import acf

5.3自己根据公式写函数

  1. def cal_acf(x, nlags):
  2.     """
  3.     按照公式自己写个acf函数
  4.     只是用来帮助理解,不建议用在别的环境中
  5.     """
  6.     x = np.array(x)
  7.     mean_x = np.mean(x)
  8.     length_x = x.shape[0]
  9.     c_0 = np.mean((x-mean_x) **2)
  10.     c_k = np.sum((x[:(length_x-nlags)] - mean_x) * (x[nlags:] - mean_x)) / length_x
  11.     r_k = c_k / c_0
  12.     return r_k

5.4两种结果对比

  1. # 结果汇总
  2. pd.DataFrame({'index':np.arange(11),
  3.              'value_by_myself':[cal_acf(x=data['value'], nlags=i) for i in range(11)],
  4.              'value_by_statsmodels':acf(data.value,nlags=10)})

结果如下:

图片

5.5自相关系数画图

画图有两种方法:

  1. 直接使用statsmodelsplot_acf;

  2. 使用acf函数来计算得到数值,得到数值后再进行可视化,这种一般便于自己定制,也方便自己做更多的细节调整之类的。

  1. # 自己画一个
  2. # 自己计算
  3. acf_value, acf_interval, _, _ = acf(data.value,nlags=14,qstat=True,alpha=0.05, fft=False)
  4. xlabel = np.arange(start=0stop=acf_value.shape[0], dtype='float')
  5. fig, ax = plt.subplots(nrows=2, figsize=(10,6), sharex=True, dpi=100)
  6. ax[0].hlines(y=0, xmin=np.min(xlabel)-2, xmax=np.max(xlabel)+2, colors='red', linewidth=0.5)
  7. ax[0].scatter(x=xlabel, y=acf_value, c='red')
  8. ax[0].vlines(x = xlabel, ymin=0, ymax=acf_value, colors='red', linewidth=0.5)
  9. xlabel[1] -= 0.5
  10. xlabel[-1+= 0.5
  11. ax[0].fill_between(x=xlabel[1:], y1=acf_interval[1:,0] - acf_value[1:], y2=acf_interval[1:, 1]-acf_value[1:], alpha=0.25, linewidth=0, color='red')
  12. ax[0].set_title("acf plot by myself")
  13. # 使用别人写好的函数
  14. from statsmodels.graphics.tsaplots import plot_acf
  15. plot_acf(data['value'], ax=ax[1])
  16. ax[1].set_title("acf plot by statsmodels")
  17. ax[1].set_xlim(-1, np.max(xlabel)+1)

图片

6.偏自相关系数

偏自相关系数可以被看成一种条件相关,两个变量之间有相关性是基于一系列的其他的条件变量。想象一个这样的问题:

我们有一个Y变量,这个Y变量和、相关,还有一个变量。那我要知道和是否相关应该怎么计算?

肯定是应该要剔除掉、对、对的影响。那么计算和的相关性就是为:

那么对于一个时间序列来说, 和之间的偏自相关系数:就是基于 、、、…… 对 和的影响,计算 和之间相关系数。

6.1偏自相关计算公式:

  1. 当h=1的时候,我们考虑的就是 和之间的偏自相关系数,这个时候中间是没有别的条件序列的,所以偏自相关系数就是等于自相关系数。

  2. 当h=2的时候,我们考虑的就是 和之间的偏自相关系数,这个时候中间的条件序列就是,所以偏自相关系数就是为:

.

  1. 当h=3的时候,我们考虑的就是 和之间的偏自相关系数,这个时候中间的条件序列就是、,所以偏自相关系数就是为:

.

  1. 依次类推。

6.2偏自相关计算:

  1. 使用statsmodels的pacf函数,这个函数可以选择不同的计算方法,有使用ols方法的,也有使用Yule-Walker方法的。

  2. 除了方法1调用包,我们还可以使用公式方法,分别使用ols方法、使用Yule-Walker方法来计算pacf的系数。实际上算出来的结果和statsmodels的pacf函数算出来的结果是一模一样的。

在下面的代码块中,我们使用statsmodels包里面的pacf、pacf_ols、pacf_yw函数计算偏自相关系数,另外我们自己通过ols理论和Yule-Walker理论计算偏自相关系数。

  1. # 使用statsmodels包的pacf函数
  2. from statsmodels.tsa.stattools import pacf,pacf_ols,pacf_yw
  3. # 自己实现用ols求解pacf的函数
  4. from numpy.dual import lstsq
  5. from statsmodels.tools import add_constant
  6. from statsmodels.tsa.tsatools import lagmat
  7. def cal_my_pacf_ols(x, nlags=5):
  8.     """
  9.     自己实现pacf,原理使用的就是ols(最小二乘法)
  10.     :param x:
  11.     :param nlags:
  12.     :return:
  13.     """
  14.     pacf = np.empty(nlags+1* 0
  15.     pacf[0= 1.0
  16.     xlags, x0 = lagmat(x, nlags, original="sep")
  17.     xlags = add_constant(xlags)
  18.     for k in range(1, nlags+1):
  19.         params = lstsq(xlags[k:, :(k+1)], x0[k:], rcond=None)[0]
  20.         pacf[k] = params[-1]
  21.     return pacf
  22. def cal_my_yule_walker(x, nlags=5):
  23.     """
  24.     自己实现yule_walker理论
  25.     :param x:
  26.     :param nlags:
  27.     :return:
  28.     """
  29.     x = np.array(x, dtype=np.float64)
  30.     x -= x.mean()
  31.     n = x.shape[0]
  32.     r = np.zeros(shape=nlags+1, dtype=np.float64)
  33.     r[0= (x ** 2).sum()/n
  34.     for k in range(1, nlags+1):
  35.         r[k] = (x[0:-k] * x[k:]).sum() / (n-k*1)
  36.     from scipy.linalg import toeplitz
  37.     R = toeplitz(c=r[:-1])
  38.     result = np.linalg.solve(R, r[1:])
  39.     return result
  40. def cal_my_pacf_yw(x, nlags=5):
  41.     """
  42.     自己通过yule_walker方法求出pacf的值
  43.     :param x:
  44.     :param nlags:
  45.     :return:
  46.     """
  47.     pacf = np.empty(nlags+1* 0
  48.     pacf[0= 1.0
  49.     for k in range(1, nlags+1):
  50.         pacf[k] = cal_my_yule_walker(x,nlags=k)[-1]
  51.     return pacf
  52. cal_my_pacf_yw(x=data.values)
  53. # 结果比较
  54. pd.DataFrame({'pacf':pacf(data.value,nlags=5method='ols'),
  55.               'pacf_ols':pacf_ols(data.value,nlags=5),
  56.               'pacf_yw':pacf_yw(data.value,nlags=5),
  57.               'pacf_ols_bymyself':cal_my_pacf_ols(x=data.values),
  58.               'pacf_yw_bymyself':cal_my_pacf_yw(x=data.values)})

效果对比:

图片

6.3偏自相关系数画图

画图有两种方法:

  1. 直接使用statsmodelsplot_pacf;

  2. 使用pacf函数来计算数据,得到数据后再进行可视化,这种一般便于自己定制,也方便自己做更多的细节调整之类的。

  1. #%%
  2. sunspotarea = pd.read_csv("../datasets/sunspotarea.csv",parse_dates=['date'])
  3. # 自己画一个
  4. # 自己计算
  5. pacf_value, pacf_interval = pacf(sunspotarea.value,nlags=15,alpha=0.05)
  6. xlabel = np.arange(start=0stop=pacf_value.shape[0], dtype='float')
  7. fig, ax = plt.subplots(nrows=2, figsize=(10,6), sharex=True, dpi=100)
  8. ax[0].hlines(y=0, xmin=np.min(xlabel)-2, xmax=np.max(xlabel)+2, colors='red', linewidth=0.5)
  9. ax[0].scatter(x=xlabel, y=pacf_value, c='red')
  10. ax[0].vlines(x = xlabel, ymin=0, ymax=pacf_value, colors='red', linewidth=0.5)
  11. xlabel[1] -= 0.5
  12. xlabel[-1+= 0.5
  13. ax[0].fill_between(x=xlabel[1:], y1=pacf_interval[1:,0] - pacf_value[1:], y2=pacf_interval[1:, 1]-pacf_value[1:], alpha=0.25, linewidth=0, color='red')
  14. ax[0].set_title("pacf plot by myself")
  15. # 使用别人写好的函数
  16. from statsmodels.graphics.tsaplots import plot_pacf
  17. plot_pacf(sunspotarea.value, ax=ax[1], lags=15)
  18. ax[1].set_title("pacf plot by statsmodels")
  19. ax[1].set_xlim(-1, np.max(xlabel)+1)

图片

写到后面

  1. 本文主要强调的是如何手写代码复现acf和pacf计算以及可视化。个人建议多多看看Yule-Walker方法计算pacf的代码。

  2. 后续会出一个教程,介绍Yule-Walker方程的意义、复现、代码等。

  3. 这期之所以会隔这么多天,是在计算pacf的时候,卡住了。后来看了很多资料,终于搞懂了原理和复现出代码。

  4. 祝大家国庆快乐~

阅读更多

python与时间序列(开篇)

python与时间序列-基本案例教程1(1.47万字,19个图,阅读需要37分钟)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/656128
推荐阅读
相关标签
  

闽ICP备14008679号