web-dev-qa-db-ja.com

matplotlibのplt.acorrの自己相関プロットのバグ?

私はPythonとの自己相関をプロットしています。私はそれを行うために3つの方法を使用しました:1。パンダ、2。matplotlib、3。statsmodels。 matplotlibから取得したグラフは、他の2つと一致していないことがわかりました。コードは次のとおりです。

 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=

12
Wu Fuheng

これは、統計と信号処理の間の異なる一般的な定義の結果です。基本的に、信号処理の定義は、トレンド除去を処理することを前提としています。統計的定義は、平均を差し引くことがあなたがするすべてのトレンド除去であると仮定し、あなたのためにそれを行います。

まず、スタンドアロンの例で問題を示しましょう。

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()

enter image description here

それで、なぜ私はそれらがすべて正しいと言っているのですか?それらは明らかに異なります!

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()

enter image description here

これは完全に有効な自己相関です。あなたのバックグラウンドが信号処理であるか統計であるかはすべて問題です。

これは、信号処理で使用される定義です。データのトレンド除去を処理することを前提としています(plt.acorrdetrend 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()

enter image description here

ただし、まだ1つの大きな違いがあります。これは純粋にプロットの規則です。

ほとんどの信号処理の教科書(とにかく私が見た)では、「完全な」自己相関が表示され、ラグがゼロになり、結果は両側で対称になります。一方、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()

enter image description here

40
Joe Kington