- 問題
- 答え
- 解説
a と b の関係について何がわかりますか?
Python コード:
import numpy as np
from statsmodels.tsa.stattools import ccf
np.random.seed(0)
a = np.random.randn(300)
b = 0.8*np.roll(a, 3) + np.random.randn(300)*0.5
print("X:", ccf(b, a, nlags=6).round(2))
print("Y:", ccf(a, b, nlags=6).round(2))
回答の選択肢:
(A) bがaに3期先行している(bの変化が3期後にaに現れる)
(B) aがbに3期先行している(aの変化が3期後にbに現れる)
(C) aとbは同時点で強く相関しているが、ラグを取ると相関が消える
(D) aとbはどちらも、3期ごとに繰り返す自己相関(周期性)を持っている
X: [ 0.07 0.03 -0.01 0.86 -0.02 0.05] Y: [ 0.07 -0.01 0.03 -0.03 0.09 0.06]
正解: (B)
ccfは2つの系列の相互相関(クロス相関)を、ラグ0, 1, 2, …ごとに計算する関数です。statsmodelsのccf(x, y)のラグkの値は、x_{t+k}とy_tの相関、つまり「yのk期後のx」との相関を表します。
Xの行(ccf(b, a))では、ラグ3だけが0.86と大きくなっています。これは「ある時点のa」と「その3期後のb」が強く相関していることを意味します。一方、Yの行(ccf(a, b))にはどのラグにも目立つ値がなく、「bの後にaが動く」関係は見られません。したがって、aがbに3期先行していると読み取れます。データ生成でも、bは3期前のaに0.8を掛けた値を含んでいます。
回答の選択肢:
(A) bがaに3期先行している(bの変化が3期後にaに現れる)
(B) aがbに3期先行している(aの変化が3期後にbに現れる)
(C) aとbは同時点で強く相関しているが、ラグを取ると相関が消える
(D) aとbはどちらも、3期ごとに繰り返す自己相関(周期性)を持っている
- コードの解説
-
このコードは、一方が他方に遅れて反応する2つの系列を作り、引数の順序を入れ替えて相互相関を計算しています。
import numpy as np from statsmodels.tsa.stattools import ccf np.random.seed(0) a = np.random.randn(300) b = 0.8*np.roll(a, 3) + np.random.randn(300)*0.5 print("X:", ccf(b, a, nlags=6).round(2)) print("Y:", ccf(a, b, nlags=6).round(2))詳しく説明します。
ライブラリのインポート
numpy:数値計算を行うためのライブラリです。ここでは乱数生成と配列の操作に使用しています。statsmodels.tsa.stattools.ccf:2つの時系列の相互相関関数(CCF: Cross-Correlation Function)を計算する関数です。
データの生成
a = np.random.randn(300):300点のホワイトノイズです。広告出稿量や気温など、先に動く系列をイメージしてください。np.roll(a, 3):配列を後ろに3つずらします。時点tの値がa_{t-3}になります(先頭3点には末尾の値が回り込みますが、300点のうち3点なので影響はわずかです)。b = 0.8*np.roll(a, 3) + ノイズ:bは「3期前のaの0.8倍」にノイズを加えた系列です。つまりbはaに3期遅れて反応します。
相互相関の計算
ccf(b, a, nlags=6):ラグ0〜5の相互相関を計算します。ラグkの値は\mathrm{corr}(b_{t+k}, a_t)です。ccf(a, b, nlags=6):引数の順序を入れ替えたものです。ラグkの値は\mathrm{corr}(a_{t+k}, b_t)になります。nlags=6:計算する値の個数です。ラグ0から始まるため、出力はラグ0〜5の6個になります。
出力の読み方
- X(
ccf(b, a))のラグ3:0.86。「aの3期後のb」との相関が強いことを示します。 - Y(
ccf(a, b)):すべて0.1以下。「bの後のa」との相関はほとんどありません。 - ラグ0(同時点)の相関はどちらも0.07で、ほぼ0です。
- 選択肢の解説
-
(A)
bがaに3期先行している → ×
向きが逆です。ccf(b, a)のラグ3はbの3期後ではなく、aの3期後のbとの相関です。「どちらの系列をk期ずらしているか」を取り違えると、先行・遅行の判断が逆転します。CCFで最も多い読み間違いです。(B)
aがbに3期先行している → ○
正解です。\mathrm{corr}(b_{t+3}, a_t)=0.86であり、aが動いた3期後にbが動くという関係を示しています。(C)
aとbは同時点で強く相関しているが、ラグを取ると相関が消える → ×
同時点(ラグ0)の相関は0.07でほぼ0です。強い相関はラグ3にだけ現れており、むしろ「同時点では無相関で、ずらすと相関が現れる」関係です。(D)
aとbはどちらも、3期ごとに繰り返す自己相関(周期性)を持っている → ×
これは自己相関(ACF)とCCFの混同です。CCFは2つの系列の間の相関であり、各系列の内部の周期性は表しません。実際、bの自己相関をラグ1〜5で計算すると、すべて絶対値0.06以下で周期性はありません。また周期性があれば、ラグ3だけでなくラグ6, 9, …にも山が繰り返し現れるはずです。 - CCFの定義とラグの向き
-
statsmodelsの
ccf(x, y)は、次の相互相関をラグk=0, 1, 2, \ldotsについて計算します。$$
s_x, s_yは標準偏差です(既定の
r_{xy}(k) = \frac{\sum_{t=1}^{n-k}(x_{t+k}-\bar{x})(y_t-\bar{y})}{(n-k)\, s_x s_y}
$$adjusted=Trueでは分母にn-kを使います)。ポイントは、第1引数の系列をk期先にずらしていることです。呼び出し ラグkの意味 ラグkで大きいとき ccf(b, a)\mathrm{corr}(b_{t+k}, a_t) aがbにk期先行ccf(a, b)\mathrm{corr}(a_{t+k}, b_t) bがaにk期先行ccfは非負のラグしか返さないため、両方向の関係を調べるには、今回のように引数を入れ替えて2回計算する必要があります。向きに迷ったときは、
pandasのshiftで直接確かめるのが確実です。import pandas as pd pd.Series(b).corr(pd.Series(a).shift(3))
a.shift(3)は「3期前のa」なので、これは\mathrm{corr}(b_t, a_{t-3})です。結果は0.856で、ccf(b, a)のラグ3と一致します。なお、
numpy.correlateやscipy.signal.correlateは正規化の有無や出力するラグの並び方がccfと異なるため、ライブラリをまたいで結果を比べるときは特に注意しましょう。 - 有意性の目安と事前白色化
-
有意性の目安
2つの系列が無相関なホワイトノイズであれば、CCFの各値はおおよそ\pm 2/\sqrt{n}の範囲に収まります。今回はn=300なので約\pm 0.115です。ラグ3の0.86はこの範囲を大きく超えていますが、他の値はすべて範囲内です。自己相関があるとCCFは広がる
今回のaはホワイトノイズでしたが、実務のデータの多くは自己相関を持ちます。aをAR(1)過程(係数0.8)に変え、同じくbを3期遅れで反応させると、CCFは次のようになります。ラグ: 0 1 2 3 4 5 6 7 CCF : 0.61 0.69 0.80 0.95 0.79 0.69 0.61 0.54
ラグ3が最大ではあるものの、どのラグでも大きな値になり、「どのラグで影響しているか」が読み取りにくくなります。
a自身の自己相関が、CCFに混入するためです。事前白色化(プレホワイトニング)
この問題への対処法が事前白色化です。先行系列aにARモデルを当てはめ、同じフィルタを両方の系列にかけて自己相関を取り除いてから、CCFを計算します。from statsmodels.tsa.ar_model import AutoReg phi = AutoReg(a2, 1, trend='n').fit().params[0] fa, fb = a2[1:] - phi*a2[:-1], b2[1:] - phi*b2[:-1] ccf(fb, fa, nlags=8)
ラグ: 0 1 2 3 4 5 6 7 CCF : 0.03 -0.02 -0.04 0.78 -0.07 0.01 0.01 -0.03
(
a2、b2はAR(1)版のデータです。)事前白色化により、ラグ3だけがはっきりと浮かび上がりました。 - CCFと関連手法
-
手法 調べること CCFとの関係 ACF(自己相関関数) 1つの系列の、過去の自分との相関 CCFは2系列間に拡張したもの CCF(相互相関関数) 2系列間の、ラグごとの相関 先行・遅行関係とラグの探索に使う グレンジャー因果検定 一方の過去が、他方の予測を改善するか CCFで見つけたラグ関係を検定で確かめる VARモデル 複数系列の相互の動的関係 CCFで関係を把握した後のモデル化 SARIMAX(外生変数) 外生変数による内生変数の予測 CCFで見つけたラグで外生変数をずらして投入 CCFは「探索」の道具であり、関係の有無を厳密に判断するものではありません。CCFで有望なラグを見つけ、グレンジャー因果検定やVARモデル(ノック40)、外生変数付きモデルへとつなげていくのが典型的な流れです。
- 実務での注意点
-
非定常な系列はそのまま使わない
トレンドを持つ2つの系列は、無関係であってもあらゆるラグで高いCCFを示します(見せかけの相関)。CCFを計算する前に、差分を取るなどして定常化しましょう。自己相関の強い系列は事前白色化する
上で見たように、先行系列に自己相関があるとCCFが広がり、ラグの特定が難しくなります。特に日次・週次の売上や気温などは自己相関が強いため、事前白色化を検討しましょう。ラグの向きを必ず確認する
ccf(x, y)の引数の順序とラグの意味は、ライブラリごとに異なります。結論を出す前に、shiftを使った相関計算で向きを確かめる習慣をつけると安全です。相関は因果ではない
CCFでラグ3に強い相関があっても、aがbの原因であるとは限りません。両者に共通して影響する第3の要因が、異なるタイミングで両方を動かしている可能性もあります。活用例
広告出稿から売上に効果が出るまでのラグ、気温の変化から電力需要が変わるまでのラグ、景気の先行指標と業績の関係など、「何期遅れで効くか」を把握したい場面で役立ちます。見つけたラグは、予測モデルの説明変数やラグ特徴量の設計に活かせます。

