【问题标题】:bug of autocorrelation plot in matplotlib‘s plt.acorr?matplotlib 的 plt.acorr 中的自相关图错误?
【发布时间】:2015-02-16 22:16:27
【问题描述】:

我正在用 python 绘制自相关。我使用了三种方法:1. pandas,2. matplotlib,3. statsmodels。我发现我从 matplotlib 得到的图表与其他两个不一致。代码是:

 from statsmodels.graphics.tsaplots import *
 # print out data
 print mydata.values

 #1. pandas
 p=autocorrelation_plot(mydata)
 plt.title('mydata')

 #2. matplotlib
 fig=plt.figure()
 plt.acorr(mydata,maxlags=150)
 plt.title('mydata')

 #3. statsmodels.graphics.tsaplots.plot_acf
 plot_acf(mydata)
 plt.title('mydata')

图表在这里:http://quant365.com/viewtopic.php?f=4&t=33

【问题讨论】:

  • 这个问题似乎是题外话,因为它是一个错误报告
  • 错误报告不仅不属于 SO,而且您的示例无法运行(mydata 未定义并且缺少导入)并且您的图表受密码保护。不知道你期望什么样的回应。如果您想改进这个问题,我建议您专注于询问每个特定功能实际上在做什么。 matplotlib 有可能采取了不同但同样有效的方法。
  • 现在应该可以了。我不能把图表放在这里,因为图像就像quant365.com/download/file.php?id=5,不能在这里发布。
  • 这不是错误,只是plt.acorrstatsmodels 中自相关图的低级函数。在 matplotlib 版本中,您看到的是“完全”自相关,并且它没有为您“居中”(即零均值)您的数据。然而,计算是正确的。
  • 滞后 0 时,ACF 为 0.5。但是matplotlib版本显然不是0.5!怎么可能是正确的?

标签: python matplotlib pandas statsmodels


【解决方案1】:

这是统计和信号处理之间不同的共同定义的结果。基本上,信号处理定义假设您要处理去趋势。统计定义假定减去均值就是您要做的所有去趋势化操作,并且会为您完成。

首先,让我们用一个独立的例子来演示这个问题:

import numpy as np
import matplotlib.pyplot as plt

import pandas as pd
from statsmodels.graphics import tsaplots

def label(ax, string):
    ax.annotate(string, (1, 1), xytext=(-8, -8), ha='right', va='top',
                size=14, xycoords='axes fraction', textcoords='offset points')

np.random.seed(1977)
data = np.random.normal(0, 1, 100).cumsum()

fig, axes = plt.subplots(nrows=4, figsize=(8, 12))
fig.tight_layout()

axes[0].plot(data)
label(axes[0], 'Raw Data')

axes[1].acorr(data, maxlags=data.size-1)
label(axes[1], 'Matplotlib Autocorrelation')

tsaplots.plot_acf(data, axes[2])
label(axes[2], 'Statsmodels Autocorrelation')

pd.tools.plotting.autocorrelation_plot(data, ax=axes[3])
label(axes[3], 'Pandas Autocorrelation')

# Remove some of the titles and labels that were automatically added
for ax in axes.flat:
    ax.set(title='', xlabel='')
plt.show()

那么,为什么我说他们都是正确的?它们显然不同!

让我们编写我们自己的自相关函数来演示 plt.acorr 在做什么:

def acorr(x, ax=None):
    if ax is None:
        ax = plt.gca()
    autocorr = np.correlate(x, x, mode='full')
    autocorr /= autocorr.max()

    return ax.stem(autocorr)

如果我们用我们的数据绘制它,我们将得到与plt.acorr 或多或少相同的结果(我没有正确标记滞后,只是因为我很懒):

fig, ax = plt.subplots()
acorr(data)
plt.show()

这是一个完全有效的自相关。这完全取决于您的背景是信号处理还是统计。

这是信号处理中使用的定义。假设您将处理去趋势数据(注意plt.acorr 中的detrend kwarg)。如果你想让它去趋势,你会明确地要求它(并且可能做一些比仅仅减去平均值更好的事情),否则不应该假设它。

在统计中,简单地减去平均值被认为是您想要做的去趋势。

所有其他函数都是在相关之前减去数据的平均值,类似于:

def acorr(x, ax=None):
    if ax is None:
        ax = plt.gca()

    x = x - x.mean()

    autocorr = np.correlate(x, x, mode='full')
    autocorr /= autocorr.max()

    return ax.stem(autocorr)

fig, ax = plt.subplots()
acorr(data)
plt.show()

但是,我们还有一个很大的不同。这纯粹是一个绘图约定。

在大多数信号处理教科书(无论如何我都看过)中,显示的是“完全”自相关,因此零滞后位于中心,结果在每一侧都是对称的。另一方面,R 有一个非常合理的约定,只显示它的一侧。 (毕竟对方完全是多余的。)统计绘图函数遵循 R 对流,plt.acorr 遵循 Matlab 所做的,这是相反的约定。

基本上,你会想要这个:

def acorr(x, ax=None):
    if ax is None:
        ax = plt.gca()

    x = x - x.mean()

    autocorr = np.correlate(x, x, mode='full')
    autocorr = autocorr[x.size:]
    autocorr /= autocorr.max()

    return ax.stem(autocorr)

fig, ax = plt.subplots()
acorr(data)
plt.show()

【讨论】:

  • 谢谢 我还有一件事不是很清楚。 “不过,我们还有一个很大的不同,这个纯属阴谋约定。”我可以知道它是什么绘图约定吗?我来自统计背景,对信号处理一无所知。为什么python不提供统一版本?而且我刚刚发现 pandas 中没有偏自相关,这令人失望。
  • 为什么在我的图中,滞后 0 处的自相关为 0.5?这是错误的,因为它应该是 1!但我认为我正确使用了该功能。还是我错过了什么?
  • @WuFuheng - 绘图约定是最后两个数字之间的差异:是否显示完整的对称自相关,或者只显示一半。至于为什么你的图表在滞后 0 处有 0.5,我不知道。我在滞后 0 处得到了 1 的自相关,具有完全相同的功能。
猜你喜欢
  • 1970-01-01
  • 2020-08-27
  • 1970-01-01
  • 2020-11-08
  • 1970-01-01
  • 2021-08-15
  • 1970-01-01
  • 1970-01-01
  • 2020-06-12
相关资源
最近更新 更多