【问题标题】:What's the difference between pandas ACF and statsmodel ACF?pandas ACF 和 statsmodel ACF 有什么区别?
【发布时间】:2016-07-02 12:35:36
【问题描述】:

我正在计算股票收益的自相关函数。为此,我测试了两个函数,即 Pandas 内置的 autocorr 函数和 statsmodels.tsa 提供的 acf 函数。这是在以下 MWE 中完成的:

import pandas as pd
from pandas_datareader import data
import matplotlib.pyplot as plt
import datetime
from dateutil.relativedelta import relativedelta
from statsmodels.tsa.stattools import acf, pacf

ticker = 'AAPL'
time_ago = datetime.datetime.today().date() - relativedelta(months = 6)

ticker_data = data.get_data_yahoo(ticker, time_ago)['Adj Close'].pct_change().dropna()
ticker_data_len = len(ticker_data)

ticker_data_acf_1 =  acf(ticker_data)[1:32]
ticker_data_acf_2 = [ticker_data.autocorr(i) for i in range(1,32)]

test_df = pd.DataFrame([ticker_data_acf_1, ticker_data_acf_2]).T
test_df.columns = ['Pandas Autocorr', 'Statsmodels Autocorr']
test_df.index += 1
test_df.plot(kind='bar')

我注意到他们预测的值并不相同:

造成这种差异的原因是什么,应该使用哪些值?

【问题讨论】:

  • 查看文档默认滞后是 1 用于 pandas 版本和40 用于 statsmodel
  • 尝试 unbiased=True 作为 statsmodels 版本的选项。
  • 您颠倒了图中的标签,我认为unbiased=True 应该使自相关系数更大。
  • autocorr 来自pandas 正在调用numpy.corrcoefacf 来自statsmodels 正在调用numpy.correlate。我认为挖掘这些有助于找到输出差异的根源。
  • 这里的第一条评论是对问题的回答吗?能解决这个问题就太好了

标签: python pandas statsmodels


【解决方案1】:

在以下示例中,Pandas autocorr() 函数给出了预期的结果,但 statmodels acf() 函数没有。

考虑以下系列:

import pandas as pd
s = pd.Series(range(10))

我们希望这个系列与其任何滞后系列之间存在完美的相关性,这实际上是我们使用autocorr() 函数得到的结果

[ s.autocorr(lag=i) for i in range(10) ]
# [0.9999999999999999, 1.0, 1.0, 1.0, 1.0, 0.9999999999999999, 1.0, 1.0, 0.9999999999999999, nan]

但是使用acf() 我们会得到不同的结果:

from statsmodels.tsa.stattools import acf
acf(s)
# [ 1.          0.7         0.41212121  0.14848485 -0.07878788 
#  -0.25757576 -0.37575758 -0.42121212 -0.38181818 -0.24545455]

如果我们尝试 acfadjusted=True,结果会更加出乎意料,因为对于某些滞后,结果小于 -1(请注意,相关性必须在 [-1, 1] 中)

acf(s, adjusted=True)  # 'unbiased' is deprecated and 'adjusted' should be used instead
# [ 1.          0.77777778  0.51515152  0.21212121 -0.13131313 
#  -0.51515152 -0.93939394 -1.4040404  -1.90909091 -2.45454545]

【讨论】:

    【解决方案2】:

    Pandas 和 Statsmodels 版本的区别在于均值减法和归一化/方差除法:

    • autocorr 只是将原始系列的子系列传递给 np.corrcoef。在该方法中,这些子序列的样本均值和样本方差用于确定相关系数
    • acf 相反,使用整体系列样本均值和样本方差来确定相关系数。

    对于较长的时间序列,差异可能会变小,但对于较短的时间序列,差异会很大。

    与 Matlab 相比,Pandas autocorr 函数可能对应于对(滞后)系列本身进行 Matlabs xcorr (cross-corr),而不是 Matlab 的 autocorr,后者计算样本自相关(从docs;我无法验证这一点,因为我无法访问 Matlab)。

    请参阅此 MWE 以获得说明:

    import numpy as np
    import pandas as pd
    from statsmodels.tsa.stattools import acf
    import matplotlib.pyplot as plt
    plt.style.use("seaborn-colorblind")
    
    def autocorr_by_hand(x, lag):
        # Slice the relevant subseries based on the lag
        y1 = x[:(len(x)-lag)]
        y2 = x[lag:]
        # Subtract the subseries means
        sum_product = np.sum((y1-np.mean(y1))*(y2-np.mean(y2)))
        # Normalize with the subseries stds
        return sum_product / ((len(x) - lag) * np.std(y1) * np.std(y2))
    
    def acf_by_hand(x, lag):
        # Slice the relevant subseries based on the lag
        y1 = x[:(len(x)-lag)]
        y2 = x[lag:]
        # Subtract the mean of the whole series x to calculate Cov
        sum_product = np.sum((y1-np.mean(x))*(y2-np.mean(x)))
        # Normalize with var of whole series
        return sum_product / ((len(x) - lag) * np.var(x))
    
    x = np.linspace(0,100,101)
    
    results = {}
    nlags=10
    results["acf_by_hand"] = [acf_by_hand(x, lag) for lag in range(nlags)]
    results["autocorr_by_hand"] = [autocorr_by_hand(x, lag) for lag in range(nlags)]
    results["autocorr"] = [pd.Series(x).autocorr(lag) for lag in range(nlags)]
    results["acf"] = acf(x, unbiased=True, nlags=nlags-1)
    
    pd.DataFrame(results).plot(kind="bar", figsize=(10,5), grid=True)
    plt.xlabel("lag")
    plt.ylim([-1.2, 1.2])
    plt.ylabel("value")
    plt.show()
    

    Statsmodels 使用np.correlate 对此进行优化,但这基本上是它的工作原理。

    【讨论】:

    • 但是两种计算自相关的方法中哪一种更好/正确?
    • 我认为statsmodels 方式是显而易见的。作为参考,这也是Wikipedia中指出的方式。要检查是否像 pandas 那样使用互相关也是一种有效的估计,需要查阅文献。仅供参考:虽然 statsmodels 的这种估计被认为是“无偏的”,因为我们使用 n-k 而不是 n,但根据 Wikipedia,它仍然是有偏的,因为我们使用样本均值和样本协方差进行计算。
    【解决方案3】:

    正如 cmets 中所建议的,通过将 unbiased=True 提供给 statsmodels 函数可以减少但不能完全解决问题。使用随机输入:

    import statistics
    
    import numpy as np
    import pandas as pd
    from statsmodels.tsa.stattools import acf
    
    DATA_LEN = 100
    N_TESTS = 100
    N_LAGS = 32
    
    def test(unbiased):
      data = pd.Series(np.random.random(DATA_LEN))
      data_acf_1 = acf(data, unbiased=unbiased, nlags=N_LAGS)
      data_acf_2 = [data.autocorr(i) for i in range(N_LAGS+1)]
      # return difference between results
      return sum(abs(data_acf_1 - data_acf_2))
    
    for value in (False, True):
      diffs = [test(value) for _ in range(N_TESTS)]
      print(value, statistics.mean(diffs))
    

    输出:

    False 0.464562410987
    True 0.0820847168593
    

    【讨论】:

      猜你喜欢
      • 2015-06-15
      • 2023-01-29
      • 1970-01-01
      • 1970-01-01
      • 2022-11-24
      • 2019-02-04
      • 2020-05-18
      • 1970-01-01
      • 2020-09-26
      相关资源
      最近更新 更多