先日、因果について書いたときに因果と相関は違うと言いましたが、厳密にいえば「因果のある相関」と「因果のない相関」というものがあります。
因果のある相関は例えば「アイスクリームの売上と気温の相関」が代表的だと思います。
しかし因果のない相関もあり例えば「溺死者数とアイスクリームの売上」が有名です。
因果のある相関を例にすれば明らかに原因は気温ですから「気温が上がるほどアイスクリームは売れる」という相関だけでなく因果まで一応分かります。
ですが、因果のない相関として例にすれば「アイスクリームを売らなくすれば溺死は減る」または「溺死が減ればアイスクリームが売れる」となるでしょうか?
なりませんね(まあもしかしたら溺死が減ると消費者が増えるのでアイスは売れるかもしれませんが、そういう話ではないです)。
こういった因果のない相関を一般的には疑似相関と言います。これは共通する第三の因子が影響して"見かけ上の相関"が発生しているため起こっていることになります。
例えば「アイスクリームを売らなくすれば溺死は減る」については「気温」という共通する第三の因子が影響したことで見かけ上の相関が発生します。
疑似相関を定量的に考える
共通する第三の因子が影響するというキーワードで分かると思いますが、その共通する第三の因子を考慮した相関係数を計測する事が出来ます。
これを偏相関係数といい、式は以下のようになります。
r_{xy・z}=\frac{r_{xy} - r_{yz} \times r_{xz}}{{\sqrt{1 - r_{yz}^2}\times\sqrt{1 - r_{xz}^2}}}
この偏相関係数は第三の因子を考慮した相関係数になります。そのため見たい相関係数とこの偏相関係数の差で疑似相関がある程度分かります。
コーディング
ライブラリのインポート
今回はデータの読み込みと数値計算ができればいいのでpandasとnumpyのみで大丈夫です。
import pandas as pd
import numpy as np
データの読み込み
今回は量的変数を目的変数にするためボストン住宅価格のデータセットを読み込みます。データはあらかじめCSVに直している物を読み込みます。
df = pd.read_csv("boston.csv")
df.head()
相関係数の確認
今回は相関の分析をするため相関係数を一度確認します。
df.corr()
私のPCの都合上なのかJupyter Notebookの仕様上なのか分かりませんが見切れていますが相関係数はこのようになっています。
偏相関係数算出関数
偏相関係数を毎回計算するプログラムを作るのは明らかに手間がかかるので関数にします。
def pcorr(xy, yz, zx):
return (xy - yz * zx) / (np.sqrt(1-yz**2) * np.sqrt(1-zx**2))
実際に計算してデータを収集
相関行列と偏相関係数を基に実際に計算してみます。
pcor = []
corr = df.corr()
columns = df.corr().columns
for i in range(len(columns)):
for j in range(i+1, len(columns)):
for k in range(len(columns)):
if columns[i] != columns[k] and columns[j] != columns[k]:
pcor.append([columns[i],
columns[j],
columns[k],
corr.loc[columns[i], columns[j]],
pcorr(corr.loc[columns[i], columns[j]], corr.loc[columns[j], columns[k]], corr.loc[columns[k], columns[i]]),
abs(corr.loc[columns[i], columns[j]]-pcorr(corr.loc[columns[i], columns[j]], corr.loc[columns[j], columns[k]], corr.loc[columns[k], columns[i]]))])
df_pcor = pd.DataFrame(pcor)
df_pcor.columns = ["因子1", "因子2", "第三の因子", "相関係数", "偏相関係数", "偏相関係数と相関係数の差"]
df_pcor.sort_values("偏相関係数と相関係数の差", ascending=False)
と実際に出力したわけですが、大きい差だと相関係数の正負が変わるくらいの物もある事が分かります。
ボストン住宅価格の偏相関係数
これが本題なのですが、ボストン住宅価格のデータセットは目的変数がその名の通り「ボストン住宅価格」になります。変数名は「PRICE」です。この相関が実際に疑似相関があるのか見てみます。
df_pcor[df_pcor["因子1"]=="PRICE"].sort_values("偏相関係数と相関係数の差", ascending=False)
実際に値を見てみると少し相関がある物が実際にはほぼ無相関になっている形で疑似相関になっていることが分かります。
まとめ
今回扱った疑似相関と偏相関係数ですが、実際にデータ分析をしていく中で「これとこれは相関があるから関係性がある」と安易に決めるのは実際にはあまりよくなく、しっかり偏相関係数を計算して疑似相関が発生しているか必ず確認しましょう。
もし疑似相関があった場合はどれだけ因果を考えても見つかりませんので疑似相関を考察する事は非常に役に立ちますし、何より重回帰分析も原因変数がどれか分からなかったらただの相関でしかないので機械学習を使う上でも考えないといけない事です。