相互相関係数について
解決したいこと
相互相関係数の計算式は以下の通りです。

x, yをそれぞれ正規化し、分子にxとyの共分散、分母に両者の標準偏差の積を用いています。
ここで注意したいのが、
分子ではn-τ個のデータを、分母ではn個のデータを使っていることです。
n : 全体のデータの数、τ : ラグ (lag)
分子、分母ともにn-τ個のデータを使って相関係数を求めるほうが直感的です。
分母の値をラグτにかかわらず固定しているのは、何の意味があるのでしょうか?
分母の値を固定することの影響
分母の値を固定すると、ラグτ (の絶対値) が大きくなってデータの重なり範囲が減るほど、相互相関係数は減衰します。
ここで、下記のデータx, yを用意しました (軸ラベルがなくてすみません)。
これら2つのデータには周期があり、360ごとにぴったり同じ形になります。
x, yのラグは30に設定しているため、30、390、750…とずらしたところで、相関係数は1になります。
このデータを使って、相互相関係数、私が提案した重複範囲のみで計算する相関係数をそれぞれ求めました。
相互相関解析の結果

ラグが大きくなるにつれて減衰しました。
有意検定も実施しました (ソースコード参照) が、臨界値もともに減衰しています。
使用したデータは自己相関があるため独立していませんが、ここではデータが独立であることを前提にした有意検定を参考にしています。
重複範囲のみの相関係数
データ数が不足しているせいで端がすこしおかしいですが、減衰はしていません。
有意検定 (ソースコード参照) では、臨界値はラグが大きくなるにつれて増大しています。
先ほどの有意検定と同様、データが独立であることを前提とする。
ソースコード
import numpy as np
import pandas as pd
import math
from matplotlib.pyplot import xcorr
from scipy import stats
def xcorr_standardized(x, y):
x = np.array(x)
y = np.array(y)
x_mean = np.mean(x)
y_mean = np.mean(y)
x_std = np.std(x)
y_std = np.std(y)
if x_std == 0 or y_std == 0:
raise ValueError("標準偏差が0のため、相関係数を計算できません。")
x_standardized = (x - x_mean) / x_std
y_standardized = (y - y_mean) / y_std
ML = math.floor(n - 1)
lags, xc_mp, fig, ax = xcorr(x_standardized, y_standardized, maxlags=ML)
xc_mp = np.flipud(xc_mp)
return lags, xc_mp
## 有意検定
def significanct_values(n, lags, co_mp, alpha):
dofs = {} #有効自由度
thresholds = {} #臨界値
for a in alpha:
dofs[a] = []
thresholds[a] = []
for i, lag in enumerate(lags):
dof = (n - abs(lag)) - 2
dofs[a].append(dof)
t_value = stats.t.ppf(1 - (a / 2), dof) #t分布の逆関数
threshold = ((n - abs(lags)) / n) * (t_value / np.sqrt(dof + t_value**2))
thresholds[a].append(threshold)
return dofs, thresholds
import numpy as np
import pandas as pd
from scipy import stats
def correlation_standardized(x, y, max_lag=None):
x = np.array(x)
y = np.array(y)
n = len(x)
if max_lag is None:
max_lag = n - 1
x_mean = np.mean(x)
y_mean = np.mean(y)
x_std = np.std(x)
y_std = np.std(y)
if x_std == 0 or y_std == 0:
raise ValueError("標準偏差が0のため、相関係数を計算できません。")
x_standardized = (x - x_mean) / x_std
y_standardized = (y - y_mean) / y_std
lags = list(range(-max_lag, max_lag + 1))
co_mp = []
for lag in lags:
if lag < 0:
xs = x_standardized[:lag]
ys = y_standardized[-lag:]
elif lag > 0:
xs = x_standardized[lag:]
ys = y_standardized[:-lag]
else:
xs = x_standardized
ys = y_standardized
r = np.sum((xs - np.mean(xs)) * (ys - np.mean(ys))) / ((len(xs) - 1) * np.std(xs, ddof=1) * np.std(ys, ddof=1))
co_mp.append(r)
return lags, co_mp
## 有意検定
def significanct_values(n, lags, co_mp, alpha):
dofs = {} #有効自由度
thresholds = {} #臨界値
for a in alpha:
dofs[a] = []
thresholds[a] = []
for i, lag in enumerate(lags):
dof = (n - abs(lag)) - 2
dofs[a].append(dof)
t_value = stats.t.ppf(1 - (a / 2), dof) #t分布の逆関数
threshold = t_value / np.sqrt(dof + t_value**2)
thresholds[a].append(threshold)
return dofs, thresholds
まとめ
分母の値をラグτにかかわらず固定している相互相関係数では、ラグが大きくなるにつれて減衰してしまいます。
なぜ固定するのか、ご存じの方がいましたら教えていただけますと幸いです。

