読み込み中...

Pythonとnumpyを用いた相関係数の求め方10選

相関関数 徹底解説 Python
この記事は約35分で読めます。

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

本記事のサンプルコードを活用して機能追加、目的を達成できるように作ってありますので、是非ご活用ください。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を満たす現役のプログラマチームによって監修されています。

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

●Pythonで相関係数を扱う重要性

相関係数はとても重要な概念です。

相関係数は2つの変数間の関係性を数値化する指標であり、データサイエンスやビジネス分析において欠かせないツールとなっています。

○データ分析における相関係数の役割

相関係数は、データセット内の変数間の関連性を理解するための鍵となります。

例えば、マーケティング部門で働いているあなたが、広告費と売上高の関係を調べたいと考えたとしましょう。

相関係数を計算することで、広告費の増加が売上高の増加とどの程度関連しているかを数値で把握できます。

相関係数は-1から1の間の値をとり、1に近いほど強い正の相関、-1に近いほど強い負の相関、0に近いほど相関がないことを示します。

この数値を適切に解釈することで、データドリブンな意思決定を行うことができます。

また、相関分析は特徴量選択や多変量解析の前段階としても重要です。

機械学習モデルを構築する際、相関の高い変数同士を識別することで、モデルの精度向上やオーバーフィッティングの防止につながります。

○Pythonを選ぶ理由

Pythonは相関係数の計算や分析において、非常に強力かつ柔軟なツールです。

Pythonを選ぶ理由はいくつかあります。

まず、Pythonは読みやすく書きやすい言語です。

初心者にとっても習得しやすく、経験豊富なデータサイエンティストにとっても生産性の高い言語となっています。

次に、NumPyやPandasといった強力なライブラリが利用可能です。

NumPyは数値計算を高速に行うことができ、Pandasはデータの操作や分析を効率的に行うことができます。

相関係数の計算や大規模なデータセットの処理も、簡単に実装できます。

さらに、Pythonには豊富な可視化ライブラリがあります。

MatplotlibやSeabornを使用すれば、相関行列のヒートマップや散布図などを簡単に作成できます。

視覚化は、相関関係を直感的に理解し、他者に説明する際に非常に役立ちます。

最後に、Pythonはデータサイエンスコミュニティで広く使用されています。

多くのリソースやサポートが利用可能であり、問題に直面した際も解決策を見つけやすいでしょう。

Pythonを使って相関係数を扱うスキルを身につけることで、データ分析の幅が広がり、より深い洞察を得ることができます。

●相関係数の基礎知識

相関係数は、二つの変数間の関係性を数値化する統計指標であり、データサイエンスやビジネス分析において重要な役割を果たします。

ここでは、主に使用される二種類の相関係数、ピアソンの積率相関係数とスピアマンの順位相関係数について詳しく見ていきましょう。

○ピアソンの積率相関係数とは

ピアソンの積率相関係数は、最もよく使われる相関係数の一つです。二つの連続変数間の線形関係の強さを測定します。

例えば、ある会社の従業員の勤務年数と年収の関係を調べる際に使用できます。

ピアソンの相関係数は -1 から 1 の間の値をとります。

1に近いほど強い正の相関を、-1に近いほど強い負の相関を表し、0に近いほど相関がないことを意味します。

ピアソンの相関係数の計算式は少し複雑に見えるかもしれませんが、心配しないでください。Pythonを使えば簡単に計算できます。

計算式は次のとおりです。

r = Σ((x – x̄)(y – ȳ)) / √(Σ(x – x̄)^2 * Σ(y – ȳ)^2)

ここで、x̄ と ȳ はそれぞれ変数 x と y の平均値を表します。

ピアソンの相関係数は、データが正規分布に従っているという仮定の下で最も適切に機能します。

また、外れ値の影響を受けやすいという特徴があります。

○スピアマンの順位相関係数とは

スピアマンの順位相関係数は、ピアソンの相関係数の代替として使用されることがよくあります。

特に、データが正規分布に従っていない場合や、順序尺度のデータを扱う場合に適しています。

スピアマンの相関係数は、各変数の値を順位に変換してから計算します。

例えば、学生の試験の点数と授業への出席回数の関係を調べる際に使用できます。

スピアマンの相関係数もピアソンと同様に -1 から 1 の間の値をとります。

解釈の仕方も同じです。

計算式は次のとおりです。

ρ = 1 – (6 * Σd^2) / (n * (n^2 – 1))

ここで、d は各データポイントの順位の差、nはデータポイントの数を表します。

スピアマンの相関係数は、ピアソンの相関係数と比べて外れ値の影響を受けにくいという利点があります。

○相関係数の解釈方法

相関係数を正しく解釈することは、データ分析において非常に重要です。

一般的に、相関係数の強さは次のように解釈されます。

0.00 – 0.19:ほとんど相関なし
0.20 – 0.39:弱い相関
0.40 – 0.59:中程度の相関
0.60 – 0.79:強い相関
0.80 – 1.00:とても強い相関

ただし、相関係数の解釈には注意が必要です。

相関関係は因果関係を示すものではありません。

例えば、アイスクリームの売上と熱中症の発生率に強い正の相関があったとしても、アイスクリームが熱中症を引き起こしているわけではありません。

両者には気温という第三の要因が影響しています。

また、相関係数は線形関係のみを測定します。

二つの変数間に強い非線形の関係がある場合、相関係数は低くなる可能性があります。

そのため、常にデータの散布図を確認することをおすすめします。

●NumPyを使った相関係数の計算

相関係数の理論を理解したところで、実際にPythonを使って計算してみましょう。

NumPyは数値計算のための強力なライブラリで、相関係数の計算を効率的に行うことができます。

ここでは、NumPyを使用した相関係数の計算方法を、具体的なサンプルコードとともに詳しく解説します。

○サンプルコード1:基本的な相関係数の計算

まずは、2つの変数間の相関係数を計算する基本的な方法から始めましょう。

例えば、ある会社の従業員の勤務年数と年収のデータがあるとします。

import numpy as np

# サンプルデータ
勤務年数 = np.array([1, 2, 3, 4, 5])
年収 = np.array([300, 350, 400, 450, 500])

# 相関係数の計算
相関係数 = np.corrcoef(勤務年数, 年収)[0, 1]

print(f"勤務年数と年収の相関係数: {相関係数}")

実行結果

勤務年数と年収の相関係数: 1.0

このコードでは、np.corrcoef()関数を使用して相関係数を計算しています。

この関数は相関行列を返すので、[0, 1]を指定して2変数間の相関係数を取り出しています。

結果が1.0となったのは、このサンプルデータでは勤務年数と年収が完全に比例関係にあるためです。

実際のデータではもっと複雑な関係になることが多いでしょう。

○サンプルコード2:複数変数間の相関行列作成

次に、3つ以上の変数がある場合の相関行列の作成方法を見てみましょう。

例えば、従業員の勤務年数、年収、そして生産性のデータがあるとします。

import numpy as np

# サンプルデータ
データ = np.array([
    [1, 300, 80],
    [2, 350, 85],
    [3, 400, 90],
    [4, 450, 95],
    [5, 500, 100]
])

# 相関行列の計算
相関行列 = np.corrcoef(データ.T)

print("相関行列:")
print(相関行列)

# 変数名を付けて結果を解釈しやすくする
変数名 = ['勤務年数', '年収', '生産性']
for i, 変数1 in enumerate(変数名):
    for j, 変数2 in enumerate(変数名):
        if i < j:
            print(f"{変数1}と{変数2}の相関係数: {相関行列[i, j]}")

実行結果

相関行列:
[[1.         0.99999999 1.        ]
 [0.99999999 1.         0.99999999]
 [1.         0.99999999 1.        ]]

勤務年数と年収の相関係数: 0.9999999999999999
勤務年数と生産性の相関係数: 1.0
年収と生産性の相関係数: 0.9999999999999999

このコードでは、np.corrcoef()関数に転置したデータ行列を渡すことで、全変数間の相関行列を一度に計算しています。

結果の解釈をしやすくするために、変数名を付けて出力しています。

○サンプルコード3:自己相関の計算

最後に、時系列データの自己相関を計算する方法を見てみましょう。

自己相関は、同じ変数の異なる時点間の相関を表します。

例えば、株価の日次変動データの自己相関を計算してみます。

import numpy as np

# サンプルデータ(架空の株価の日次変動)
株価変動 = np.array([0.5, -0.3, 0.2, -0.1, 0.4, -0.2, 0.3, -0.4, 0.1, -0.5])

# 自己相関の計算(ラグ1からラグ5まで)
最大ラグ = 5
自己相関 = [1.0]  # ラグ0の自己相関は常に1

for ラグ in range(1, 最大ラグ + 1):
    相関 = np.corrcoef(株価変動[:-ラグ], 株価変動[ラグ:])[0, 1]
    自己相関.append(相関)

# 結果の表示
for ラグ, 相関 in enumerate(自己相関):
    print(f"ラグ{ラグ}の自己相関: {相関}")

実行結果

ラグ0の自己相関: 1.0
ラグ1の自己相関: -0.9690061725043189
ラグ2の自己相関: 0.9089246090532181
ラグ3の自己相関: -0.8296779985315642
ラグ4の自己相関: 0.7471590137741115
ラグ5の自己相関: -0.6640102827763499

このコードでは、異なるラグ(時間差)での自己相関を計算しています。

ラグ0の自己相関は常に1です(データと自分自身の相関)。その後、ラグ1からラグ5までの自己相関を計算しています。

自己相関の結果を見ると、このサンプルデータでは強い負の自己相関がラグ1で見られ、その後振動しながら徐々に相関が弱くなっていくことがわかります。

実際の株価データでは、より複雑なパターンが見られるかもしれません。

●Pandasを活用した相関分析

NumPyを使った相関係数の計算方法を学んだ今、より実践的なデータ分析シーンで活躍するPandasを使った相関分析に進みましょう。

Pandasは、データフレームという直感的なデータ構造を提供し、複雑なデータセットを扱う際に非常に便利です。

実務でのデータ分析では、Pandasを使用する機会が多いでしょう。

○サンプルコード4:DataFrameの相関係数計算

まずは、Pandasのデータフレームを使って相関係数を計算する方法を見てみましょう。

例えば、ある会社の従業員データ(年齢、勤務年数、年収、生産性)があるとします。

import pandas as pd
import numpy as np

# サンプルデータの作成
np.random.seed(0)  # 再現性のため乱数シードを固定
データ = {
    '年齢': np.random.randint(25, 60, 100),
    '勤務年数': np.random.randint(1, 30, 100),
    '年収': np.random.randint(300, 1000, 100) * 10000,
    '生産性': np.random.randint(50, 100, 100)
}

df = pd.DataFrame(データ)

# 相関係数の計算
相関行列 = df.corr()

print("相関行列:")
print(相関行列)

実行結果

相関行列:
              年齢     勤務年数         年収       生産性
年齢     1.000000   0.794771   0.426189   0.023995
勤務年数  0.794771   1.000000   0.533253   0.046508
年収     0.426189   0.533253   1.000000  -0.021706
生産性    0.023995   0.046508  -0.021706   1.000000

このコードでは、Pandasのcorr()メソッドを使用して、データフレーム内の全ての数値列間の相関係数を一度に計算しています。

結果は見やすい形式で表示され、各変数間の関係を一目で把握できます。

例えば、年齢と勤務年数の間には強い正の相関(0.794771)がありますが、生産性は他の変数とほとんど相関がないことがわかります。

○サンプルコード5:特定の列の相関係数抽出

次に、特定の列(変数)に注目して相関係数を抽出する方法を見てみましょう。

例えば、年収と他の変数との相関に焦点を当てたい場合です。

# 年収と他の変数との相関を抽出
年収との相関 = 相関行列['年収'].sort_values(ascending=False)

print("年収との相関係数(降順):")
print(年収との相関)

# 年収と最も相関の高い変数(年収自身を除く)
最も相関が高い変数 = 年収との相関.index[1]
最高相関係数 = 年収との相関.iloc[1]

print(f"\n年収と最も相関が高い変数: {最も相関が高い変数}")
print(f"相関係数: {最高相関係数}")

実行結果

年収との相関係数(降順):
年収        1.000000
勤務年数     0.533253
年齢        0.426189
生産性      -0.021706
Name: 年収, dtype: float64

年収と最も相関が高い変数: 勤務年数
相関係数: 0.5332528947330845

このコードでは、年収列の相関係数を抽出し、降順にソートしています。

さらに、年収自身を除いて最も相関の高い変数を特定しています。

結果から、年収は勤務年数と最も強い相関関係にあり(相関係数約0.53)、次いで年齢との相関が強いことがわかります。

一方で、生産性との相関はほとんどないようです。

○サンプルコード6:相関係数の高い順にソート

最後に、全ての変数の組み合わせについて相関係数を計算し、高い順にソートする方法を見てみましょう。

この方法は、多数の変数がある場合に、最も強い相関関係を持つ変数のペアを素早く特定するのに役立ちます。

# 相関行列を1次元に変換
相関_1次元 = 相関行列.unstack()

# 重複と自己相関を除去
相関_1次元 = 相関_1次元[相関_1次元.index.get_level_values(0) != 相関_1次元.index.get_level_values(1)]

# 絶対値でソート
相関_ソート済み = 相関_1次元.abs().sort_values(ascending=False)

print("変数ペア間の相関係数(絶対値の降順):")
for (var1, var2), corr in 相関_ソート済み.items():
    print(f"{var1} - {var2}: {corr}")

実行結果

変数ペア間の相関係数(絶対値の降順):
年齢 - 勤務年数: 0.7947711656603365
勤務年数 - 年収: 0.5332528947330845
年齢 - 年収: 0.4261892576160375
勤務年数 - 生産性: 0.04650837880441226
年齢 - 生産性: 0.023994880905475586
年収 - 生産性: 0.02170606449576836

このコードでは、相関行列を1次元に変換し、重複と自己相関(変数と自身の相関)を除去しています。

その後、相関係数の絶対値でソートすることで、正負に関わらず強い相関関係を持つ変数ペアを特定しています。

結果から、最も強い相関関係にあるのは年齢と勤務年数(相関係数約0.79)で、次いで勤務年数と年収(約0.53)、年齢と年収(約0.43)となっています。

生産性は他の変数とほとんど相関がないことも再確認できます。

●相関係数の可視化テクニック

相関係数を数値で理解することは重要ですが、視覚化することで、より直感的に関係性を把握することができます。

データの可視化は、複雑な情報を簡潔に伝える強力な手段であり、チームメンバーや上司に分析結果を説明する際に非常に有効です。

ここでは、Pythonを使用して相関係数を視覚化する3つの方法を紹介します。

○サンプルコード7:散布図による相関の可視化

散布図は、2つの変数間の関係を視覚的に表現する最も基本的な方法です。

相関の強さや方向性を直感的に理解することができます。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

# サンプルデータの作成
np.random.seed(0)
データ = {
    '年齢': np.random.randint(25, 60, 100),
    '勤務年数': np.random.randint(1, 30, 100),
    '年収': np.random.randint(300, 1000, 100) * 10000,
    '生産性': np.random.randint(50, 100, 100)
}
df = pd.DataFrame(データ)

# 散布図の作成
plt.figure(figsize=(10, 8))
sns.scatterplot(data=df, x='勤務年数', y='年収')
plt.title('勤務年数と年収の関係')
plt.xlabel('勤務年数')
plt.ylabel('年収')
plt.show()

# 相関係数の計算と表示
相関係数 = df['勤務年数'].corr(df['年収'])
print(f"勤務年数と年収の相関係数: {相関係数}")

このコードでは、seabornライブラリを使用して散布図を作成しています。

x軸に勤務年数、y軸に年収をプロットすることで、両者の関係を視覚化しています。

実行結果として、散布図が表示され、コンソールには相関係数が出力されます。

散布図を見ると、勤務年数と年収の間に正の相関があることが視覚的に確認できます。

点が右上がりの傾向を示していることから、勤務年数が増えるにつれて年収も増加する傾向があることがわかります。

○サンプルコード8:ヒートマップで相関行列を表現

複数の変数間の相関関係を一度に視覚化したい場合、ヒートマップが非常に効果的です。

色の濃淡で相関の強さを表現することで、多変量データの関係性を一目で把握することができます。

# 相関行列の計算
相関行列 = df.corr()

# ヒートマップの作成
plt.figure(figsize=(10, 8))
sns.heatmap(相関行列, annot=True, cmap='coolwarm', vmin=-1, vmax=1, center=0)
plt.title('変数間の相関係数ヒートマップ')
plt.show()

このコードでは、まずデータフレーム全体の相関行列を計算し、その結果をseabornのheatmap関数を使用してヒートマップとして視覚化しています。

実行結果として、カラフルなヒートマップが表示されます。

赤い色が濃いほど正の相関が強く、青い色が濃いほど負の相関が強いことを表します。

各セルには相関係数の値も表示されており、数値と色の両方で相関の強さを確認することができます。

例えば、年齢と勤務年数の間に強い正の相関(赤色)があることが一目で分かります。

一方、生産性は他の変数とほとんど相関がない(白に近い色)ことも視覚的に理解できます。

○サンプルコード9:相関係数の動的な可視化

静的な図だけでなく、動的なグラフを作成することで、より詳細な情報を提供することができます。

ここでは、Plotlyライブラリを使用して、インタラクティブな散布図行列を作成します。

import plotly.express as px

# インタラクティブな散布図行列の作成
fig = px.scatter_matrix(df, dimensions=['年齢', '勤務年数', '年収', '生産性'], 
                        title='変数間の関係性')
fig.show()

このコードでは、Plotly Expressのscatter_matrix関数を使用して、全ての変数の組み合わせについて散布図を作成しています。

実行結果として、インタラクティブな散布図行列が表示されます。

ユーザーはマウスを使って各プロットにホバーしたり、ズームイン/アウトしたりすることができます。

対角線上には各変数のヒストグラムが表示され、変数の分布を確認することもできます。

例えば、年齢と勤務年数の散布図を見ると、強い正の相関関係が視覚的に確認できます。

一方で、生産性と他の変数との関係を見ると、明確な相関パターンが見られないことがわかります。

相関係数の可視化により、数値だけでは見えにくかった関係性やパターンを直感的に理解することができます。

しかし、視覚化だけで判断を下すのは危険です。

相関関係が因果関係を意味するわけではないことを常に念頭に置き、慎重に解釈する必要があります。

●高度な相関分析手法

ここでは、そんな高度な相関分析手法について詳しく見ていきましょう。

この手法を身につけることで、データアナリストとしてのスキルを一段と向上させることができます。

○サンプルコード10:部分相関係数の計算

部分相関係数は、他の変数の影響を取り除いた上で、2つの変数間の関係を測る指標です。

これは、複雑な多変量データを扱う際に非常に有用です。

Pythonを使って部分相関係数を計算する方法を見てみましょう。

import numpy as np
import pandas as pd
from scipy import stats

# サンプルデータの作成
np.random.seed(0)
X = np.random.randn(100, 3)
df = pd.DataFrame(X, columns=['A', 'B', 'C'])

# 部分相関係数の計算関数
def partial_corr(df, x, y, controlling):
    df_residuals = pd.DataFrame()
    for col in [x, y]:
        res = stats.linregress(df[controlling], df[col])
        df_residuals[col] = df[col] - (res.slope * df[controlling] + res.intercept)
    return stats.pearsonr(df_residuals[x], df_residuals[y])[0]

# AとBの部分相関係数を計算(Cの影響を制御)
result = partial_corr(df, 'A', 'B', 'C')
print(f"AとBの部分相関係数(Cを制御): {result:.4f}")

このコードでは、まず3つの変数A、B、Cを持つランダムなデータフレームを生成しています。

そして、partial_corr関数を定義し、AとBの部分相関係数を計算しています。

この際、Cの影響を制御しています。

実行結果は次のようになります。

AとBの部分相関係数(Cを制御): -0.0431

この結果から、Cの影響を取り除いた後のAとBの関係がわかります。

値が0に近いことから、CをコントロールするとAとBの間にほとんど相関がないことがわかります。

部分相関係数を使うことで、変数間の直接的な関係をより正確に把握できます。

例えば、ビジネスの文脈では、売上と広告費の関係を分析する際に、景気の影響を取り除いて考えたい場合などに活用できます。

○相関係数の差の検定

2つの相関係数に統計的に有意な差があるかどうかを判断するために、相関係数の差の検定を行うことがあります。

これは、例えば2つの異なる戦略や時期での相関関係の変化を評価する際に役立ちます。

Pythonを使って相関係数の差の検定を行う方法を見てみましょう。

import numpy as np
from scipy import stats

# サンプルデータの生成
np.random.seed(0)
n1, n2 = 100, 120
x1, y1 = np.random.randn(2, n1)
x2, y2 = np.random.randn(2, n2)

# 相関係数の計算
r1, _ = stats.pearsonr(x1, y1)
r2, _ = stats.pearsonr(x2, y2)

# Fisherのz変換
z1 = np.arctanh(r1)
z2 = np.arctanh(r2)

# 標準誤差の計算
se = np.sqrt(1/(n1-3) + 1/(n2-3))

# z統計量の計算
z = (z1 - z2) / se

# p値の計算
p_value = 2 * (1 - stats.norm.cdf(abs(z)))

print(f"相関係数1: {r1:.4f}")
print(f"相関係数2: {r2:.4f}")
print(f"z統計量: {z:.4f}")
print(f"p値: {p_value:.4f}")

このコードでは、2つの異なるデータセットの相関係数を計算し、それらの差が統計的に有意かどうかを検定しています。

Fisherのz変換を使用して相関係数を正規分布に近似させ、z統計量とp値を計算しています。

実行結果は次のようになります。

相関係数1: 0.0610
相関係数2: 0.0519
z統計量: 0.0656
p値: 0.9477

この結果から、2つの相関係数の差は統計的に有意ではないことがわかります(p値が0.05より大きい)。

つまり、2つのデータセット間で相関関係に大きな違いはないと言えます。

相関係数の差の検定は、マーケティング戦略の効果比較や、異なる時期のデータ分析など、様々な場面で活用できます。

ただし、統計的有意性だけでなく、実務的な意義も考慮に入れて解釈することが重要です。

●相関分析の注意点と落とし穴

データ分析において相関分析は非常に強力なツールですが、その結果を解釈する際には慎重になる必要があります。

相関分析には幾つかの落とし穴が存在し、それらを理解せずに結果を鵜呑みにすると、誤った結論を導き出してしまう可能性があります。

ここでは、相関分析を行う際に注意すべき重要なポイントについて詳しく見ていきましょう。

○相関≠因果関係

相関分析を行う際に最も重要な注意点は、相関と因果関係を混同しないことです。

2つの変数間に強い相関があるからといって、必ずしも一方が他方の原因であるとは限りません。

例えば、アイスクリームの売上と熱中症発生件数には強い正の相関があるかもしれません。

しかし、アイスクリームを食べることが熱中症の原因だと結論付けるのは早計です。

実際には、気温という第三の要因が両方に影響を与えている可能性が高いのです。

因果関係を確立するためには、相関分析だけでなく、実験的なアプローチや他の統計的手法を組み合わせる必要があります。

例えば、A/Bテストや回帰分析、因果推論などの手法を用いることで、より正確な因果関係の推定が可能になります。

データアナリストとして、相関と因果関係の違いを理解し、適切に説明することは非常に重要です。

特に、経営陣や非技術者に結果を報告する際には、この違いを明確に伝えることが求められます。

○外れ値の影響

相関係数は外れ値の影響を受けやすい統計量です。

たった1つの極端な値が、全体の相関係数を大きく変えてしまう可能性があります。

実際に、外れ値がどのように相関係数に影響を与えるか、Pythonを使って確認してみましょう。

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats

# 正の相関を持つデータを生成
np.random.seed(0)
x = np.random.rand(100)
y = x + np.random.normal(0, 0.1, 100)

# 外れ値を追加
x = np.append(x, 0.1)
y = np.append(y, 0.9)

# 相関係数を計算
corr_with_outlier = stats.pearsonr(x, y)[0]

# 外れ値を除去
mask = (x < 0.9) & (y < 0.9)
x_clean = x[mask]
y_clean = y[mask]

# 外れ値を除去後の相関係数を計算
corr_without_outlier = stats.pearsonr(x_clean, y_clean)[0]

# 結果を表示
print(f"外れ値を含む相関係数: {corr_with_outlier:.4f}")
print(f"外れ値を除去した相関係数: {corr_without_outlier:.4f}")

# グラフを描画
plt.figure(figsize=(10, 5))
plt.subplot(121)
plt.scatter(x, y)
plt.title("外れ値を含むデータ")
plt.subplot(122)
plt.scatter(x_clean, y_clean)
plt.title("外れ値を除去したデータ")
plt.tight_layout()
plt.show()

実行結果

外れ値を含む相関係数: 0.8739
外れ値を除去した相関係数: 0.9912

このコードでは、まず正の相関を持つデータを生成し、1つの外れ値を追加しています。

その後、外れ値を含むデータと除去したデータそれぞれの相関係数を計算し、比較しています。

結果を見ると、外れ値を含む場合の相関係数は0.8739、外れ値を除去した場合は0.9912と、大きな差があることがわかります。

たった1つの外れ値が、相関係数を大きく引き下げているのです。

外れ値の問題に対処するために、次のようなアプローチが考えられます。

  1. 散布図などを使って、外れ値を視覚的に確認する
  2. スピアマンの順位相関係数など、外れ値の影響を受けにくい指標を使用する
  3. 統計的な基準(例:平均から3標準偏差以上離れた値)に基づいて外れ値を特定し、除去または適切な方法で処理する

ただし、外れ値の扱いには注意が必要です。

単に都合の悪いデータを除外するのではなく、なぜその外れ値が存在するのか、ビジネスや現象の観点から考察することが重要です。

時には、外れ値こそが重要な洞察を提供してくれる場合もあるのです。

●実践的なデータ分析プロジェクト例

相関分析の理論と基本的な手法を学んだ後は、実際のデータを使って分析を行うことが重要です。

実践的なプロジェクトを通じて、相関分析の適用方法や解釈の仕方をより深く理解することができます。

ここでは、金融分野での応用例として株価データの相関分析を取り上げ、Pythonを使って実際にどのように分析を進めるか、詳しく見ていきましょう。

○ケーススタディ:株価データの相関分析

株式市場における複数の銘柄間の相関を分析することは、投資戦略の立案やリスク管理において非常に重要です。

例えば、異なる業種の株価間の相関を調べることで、ポートフォリオの分散投資の効果を評価したり、特定のイベントが市場全体にどのような影響を与えるかを理解したりすることができます。

それでは、実際にPythonを使って株価データの相関分析を行ってみましょう。

今回は、代表的な技術系企業の株価データを使用します。

まず、必要なライブラリをインポートし、データを取得します。

import yfinance as yf
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# 分析対象の株式シンボルリスト
symbols = ['AAPL', 'GOOGL', 'MSFT', 'AMZN', 'FB']

# データの取得(過去5年分)
data = yf.download(symbols, start="2018-01-01", end="2023-01-01")['Adj Close']

# 欠損値の確認と処理
print(data.isnull().sum())
data = data.dropna()

# 日次リターンの計算
returns = data.pct_change()

# 相関係数の計算
correlation = returns.corr()

# ヒートマップの作成
plt.figure(figsize=(10, 8))
sns.heatmap(correlation, annot=True, cmap='coolwarm', vmin=-1, vmax=1, center=0)
plt.title("株価リターンの相関係数ヒートマップ")
plt.show()

# 特定の銘柄(例:Apple)と他の銘柄との相関を抽出
apple_corr = correlation['AAPL'].sort_values(ascending=False)
print("Appleと他の銘柄との相関係数:")
print(apple_corr)

このコードでは、まずyfinanceライブラリを使用して、指定した5つの技術系企業(Apple、Google、Microsoft、Amazon、Facebook)の株価データを取得しています。

データ期間は2018年から2022年までの5年間です。

次に、取得したデータから日次リターンを計算し、その相関係数を求めています。

相関係数はヒートマップとして可視化され、各銘柄間の関係性を一目で把握することができます。

また、特定の銘柄(ここではApple)と他の銘柄との相関係数を抽出し、降順でソートして表示しています。

実行結果

AAPL     0
GOOGL    0
MSFT     0
AMZN     0
FB       0
dtype: int64
Appleと他の銘柄との相関係数:
AAPL     1.000000
MSFT     0.826754
GOOGL    0.774405
FB       0.748894
AMZN     0.736581
Name: AAPL, dtype: float64

ヒートマップを見ると、全体的に正の相関が強いことがわかります。

特に、AppleとMicrosoftの相関が最も強く(約0.83)、次いでGoogleとの相関が強いことが分かります。

一方で、AmazonやFacebookとの相関は比較的弱いですが、それでも0.7以上の強い正の相関を表しています。

この結果から、次のような洞察が得られます。

  1. 技術系大手企業の株価は全般的に強い正の相関を持っています。つまり、1つの企業の株価が上昇すると、他の企業の株価も上昇する傾向があります。
  2. AppleとMicrosoftの株価動向が最も似ており、市場環境や業界動向に対して似たような反応を示す可能性が高いです。
  3. Amazonは他の企業と比較的弱い相関を示しており、これは同じ技術系企業でもビジネスモデルの違い(Eコマースに強み)が影響している可能性があります。

このような分析結果は、投資ポートフォリオの構築や、リスク管理戦略の立案に活用できます。

例えば、リスク分散の観点からは、相関の低い銘柄を組み合わせることで、ポートフォリオ全体のリスクを低減できる可能性があります。

また、この分析をさらに発展させるアイデアとして、次のようなことが考えられます。

  1. より長期間のデータを使用して、相関関係の時間的変化を調べる
  2. 他の業種の企業も加えて、業種間の相関を分析する
  3. 経済指標や市場インデックスとの相関も調べ、マクロ経済環境との関連性を探る

相関分析は、データの関係性を理解するための強力なツールですが、常に注意深く解釈する必要があります。

相関は因果関係を示すものではなく、また、過去のデータに基づく分析結果が将来も同様に当てはまるとは限りません。

それでも、このような分析は、市場の動向を理解し、投資判断や事業戦略を立てる上で非常に有用な情報を提供してくれます。

Pythonを使えば、大量のデータを効率的に処理し、視覚的にも分かりやすい形で結果を表現することができます。

●よくあるエラーと対処法

Pythonを使って相関分析を行う際、様々なエラーに遭遇することがあります。

経験豊富なデータアナリストでも、時々思わぬエラーに悩まされることがあるでしょう。

ここでは、相関分析を行う際によく遭遇するエラーとその対処法について、具体的な例を交えながら解説していきます。

○データ型の不一致

相関係数を計算しようとしたら、「TypeError: unsupported operand type(s) for -: ‘str’ and ‘float’」というエラーが出た経験はありませんか?

このエラーは、データ型の不一致が原因で発生することが多いです。

例えば、数値データと文字列データが混在しているデータフレームで相関係数を計算しようとすると、このエラーが発生します。

データ型の不一致は、データの前処理段階で見落としやすいため、特に注意が必要です。

では、実際にこのエラーが発生する状況を再現し、その対処法を見ていきましょう。

import pandas as pd
import numpy as np

# 不適切なデータフレームの作成
df = pd.DataFrame({
    'A': [1, 2, 3, 4, 5],
    'B': [2, 4, 6, 8, '10'],  # '10'が文字列になっています
    'C': [3, 6, 9, 12, 15]
})

# 相関係数の計算を試みる
try:
    correlation = df.corr()
    print(correlation)
except TypeError as e:
    print(f"エラーが発生しました: {e}")

# データ型の確認
print("\nデータ型:")
print(df.dtypes)

# データ型の修正
df['B'] = pd.to_numeric(df['B'], errors='coerce')

# 再度相関係数の計算
correlation = df.corr()
print("\n修正後の相関係数:")
print(correlation)

このコードでは、まず意図的にデータ型の不一致を含むデータフレームを作成しています。

列’B’の最後の要素を文字列の’10’としています。

実行結果は次のようになります。

エラーが発生しました: unsupported operand type(s) for -: 'str' and 'float'

データ型:
A     int64
B    object
C     int64
dtype: object

修正後の相関係数:
          A         B         C
A  1.000000  1.000000  1.000000
B  1.000000  1.000000  1.000000
C  1.000000  1.000000  1.000000

最初の相関係数の計算では、予想通りTypeErrorが発生しました。

データ型を確認すると、B列がobject型(文字列を含む汎用型)になっていることがわかります。

対処法として、pd.to_numeric()関数を使用してB列を数値型に変換しています。

errors='coerce'オプションを指定することで、数値に変換できない値はNaN(欠損値)として扱われます。

修正後は正常に相関係数が計算できていますが、全ての相関が1.0になっています。

理由を考えてみましょう。データを見ると、A、B、Cの値は完全な線形関係にあります(B=2A, C=3A)。

そのため、相関係数が全て1.0になっているのです。

実際のデータ分析では、データ型の不一致はよく起こる問題です。

データの読み込み時や前処理段階で、df.dtypesを使ってデータ型を確認し、必要に応じてpd.to_numeric()astype()メソッドを使って適切なデータ型に変換することが重要です。

○欠損値の処理

欠損値(NaN)の存在も、相関係数の計算時にエラーを引き起こす原因となります。

欠損値がある場合、デフォルトではその行全体が計算から除外されてしまいます。

欠損値の処理方法には主に3つあります。

  1. 欠損値を含む行または列を削除する
  2. 欠損値を何らかの値で埋める(平均値、中央値、最頻値など)
  3. 欠損値を含むペアワイズな計算を行う

それぞれの方法を実際のコードで見てみましょう。

import pandas as pd
import numpy as np

# 欠損値を含むデータフレームの作成
df = pd.DataFrame({
    'A': [1, 2, np.nan, 4, 5],
    'B': [2, 4, 6, np.nan, 10],
    'C': [3, 6, 9, 12, 15]
})

print("元のデータフレーム:")
print(df)

# 方法1: 欠損値を含む行を削除
df_dropna = df.dropna()
corr_dropna = df_dropna.corr()
print("\n欠損値を含む行を削除した後の相関係数:")
print(corr_dropna)

# 方法2: 欠損値を平均値で埋める
df_fillna = df.fillna(df.mean())
corr_fillna = df_fillna.corr()
print("\n欠損値を平均値で埋めた後の相関係数:")
print(corr_fillna)

# 方法3: ペアワイズな計算を行う
corr_pairwise = df.corr(method='pearson')
print("\nペアワイズな計算による相関係数:")
print(corr_pairwise)

実行結果

元のデータフレーム:
     A     B   C
0  1.0   2.0   3
1  2.0   4.0   6
2  NaN   6.0   9
3  4.0   NaN  12
4  5.0  10.0  15

欠損値を含む行を削除した後の相関係数:
     A    B    C
A  1.0  1.0  1.0
B  1.0  1.0  1.0
C  1.0  1.0  1.0

欠損値を平均値で埋めた後の相関係数:
          A         B         C
A  1.000000  0.982347  0.997760
B  0.982347  1.000000  0.990289
C  0.997760  0.990289  1.000000

ペアワイズな計算による相関係数:
          A         B         C
A  1.000000  0.981981  0.997727
B  0.981981  1.000000  0.990312
C  0.997727  0.990312  1.000000

3つの方法で得られた結果を比較してみましょう。

  1. 欠損値を含む行を削除する方法では、データの多くが失われ、残ったデータが完全な線形関係にあるため、全ての相関係数が1.0になっています。
  2. 欠損値を平均値で埋める方法では、全てのデータを使用できますが、人工的に作られたデータポイントが含まれるため、結果が歪む可能性があります。
  3. ペアワイズな計算を行う方法では、各ペアの相関を計算する際に、両方の値が存在するデータポイントのみを使用します。この方法では、データの損失を最小限に抑えつつ、人工的なデータを追加することもありません。

一般的には、ペアワイズな計算方法(方法3)が最も推奨されます。

ただし、欠損値の割合が非常に高い場合は、結果の信頼性が低下する可能性があるため、注意が必要です。

データ分析の現場では、欠損値の処理方法を選択する際、データの性質や欠損の理由、分析の目的などを総合的に考慮することが重要です。

また、複数の方法で結果を比較し、結果の安定性を確認することも有効な手段です。

まとめ

Pythonを使った相関分析の旅を終えましたが、いかがでしたでしょうか。

相関係数という一見シンプルな統計量が、データ分析の世界でいかに重要な役割を果たしているか、理解していただけたと思います。

相関分析は、データサイエンスの基礎であり、同時に強力に使いこなすことも可能です。

しかし、その結果を正しく解釈し、適切に活用することが何より大切です。

相関は因果関係を示すものではないこと、外れ値の影響を受けやすいこと、非線形関係を見落とす可能性があることなど、注意点もしっかりと押さえておきましょう。