St_Hakky’s blog

Data Science / Human Resources / Web Applicationについて書きます

【Python】ピアソンの相関係数をいろいろな方法で計算する方法まとめ(SciPy / Numpy / Pandas)

こんにちは。

今日は題名の通り。

色んな所で目にするピアソンの相関係数ですが、毎回実装の方法調べちゃうので、ピアソンの相関係数をいろんな方法で計算する方法をまとめておきたいと思います。

Pearsonの(積率)相関係数とは

ピアソンの相関係数は、英語ではPearson's correlation coefficientと呼びます。相関係数にもいろいろな種類があって、ピアソンの相関係数もそのうちの一つです。

定義

以下の式で表され、-1~1の値の間で値が変化します。

$$
\frac{ \sum_{i=1}^{n} ( x_{i} - \overline{x} ) ( y_{i} - \overline{y}) }{ \sqrt{ \sum_{i=1}^{n} ( x_{i} - \overline{x})^2 } \sqrt{ \sum_{i=1}^{n} ( y_{i} - \overline{y})^2 } }
$$

使い所

変数間の直線関係の強度を知りたいときにこの相関係数を使用します。定義の式を見ると、 $x$ からその平均 $\overline{x}$ を引いたものと、 $y$ からその平均
$\overline{y}$ を引いたものの $cos$ を表していることになります。よって、「データにおいて、$x$と$y$のばらつきぐあいが完全に一致していたら、相関係数が1になる」ことがわかります。

また、ピアソンの相関係数では、変数が正規分布に従っていることを仮定しています。なので、正規分布に従っていると仮定できるデータがあったとして、そのデータの直線関係の強度を知りたい時、これは使えます。

相関係数の値と相関の強さの関係

以下のように考えるのが目安らしいです。絶対値としているので、負の相関と正の相関の両方を一度に表していますが、相関の強さという意味では変わらないので、略します。

相関係数の絶対値 強さ
0.0~0.2 相関無し
0.2~0.4 やや相関有り
0.4~0.7 強い相関がある
0.7~1.0 非常に強い相関がある

Pythonによる実装

とまぁこんな感じで定義されるピアソンの相関係数ですが、定義自体は難しくないのです。

計算方法がいくつかPythonでは用意されているので、その計算方法を思いつくものをまとめておこうと思います。

scratch

スクラッチといっても、numpy使っちゃってますが、以下のようにかけます。SciPyの方でもソースコードを見たら同じような実装をしていました。

import numpy as np

def pearson_corr(x, y):
    x_diff = x - np.mean(x)
    y_diff = y - np.mean(y)
    return np.dot(x_diff, y_diff) / (np.sqrt(sum(x_diff ** 2)) * np.sqrt(sum(y_diff ** 2)))

SciPy : scipy.spatial.distance

scipyを使った例も書いておきます。

from scipy.spatial.distance import correlation
1 - correlation(x, y)

SciPyを使った場合の注意点として、この関数では以下の式をもとに計算されているので、1から引いてあげないと相関係数が計算できないことです。

$$
1 - \frac{ \sum_{i=1}^{n} ( x_{i} - \overline{x} ) ( y_{i} - \overline{y}) }{ \sqrt{ \sum_{i=1}^{n} ( x_{i} - \overline{x})^2 } \sqrt{ \sum_{i=1}^{n} ( y_{i} - \overline{y})^2 } }
$$

そこさえ注意すれば、特に難しくないかなと思います。

SciPy : scipy.stats.pearsonr

これは、ピアソンの相関係数だけではなく、帰無仮説(無相関)と設定した場合のp値も計算してくれるっぽいです。すばらしいですね。

from scipy.stats import pearsonr
pearsonr(x, y)

例えば上のコードを実行すると、次のような感じのtupleでデータが帰ってきます。

# (ピアソンの相関係数, p値)
(1.0, 0.0)

Numpy : numpy.corrcoef

先程までのscratchで書いたものやSciPyはいずれも1d-arrayを想定していたわけですが、ここでは、2次元配列における行同士の相関も計算することができます。

まず、これまで通り1次元の配列 $x$ と $y$ を入れて計算すると以下のようになります。

import numpy as np
np.corrcoef(x, y, rowvar=True)

ここでパラメーターとして指定している rowvarは、デフォルトでTrueなので、ここでは特に意味は無いです。が、行を変数として扱うのがデフォルトなので、それを反転したいときはここをFalseにするとできます。

この時、出力は、

# 以下のように、変数同士でそれぞれ相関係数を出している。
# array([[ xx    , xy ],
#            [ yx   , yy ]])
array([[ 1.        ,  0.77658027],
       [ 0.77658027,  1.        ]])

みたいな感じで出てきます。なので、通常の相関係数が欲しい場合は、行列の要素として、[0, 1]の部分を取って来ればいいです([1, 0]は事実上同じなので)。

2次元配列でその行(または列)同士の相関を見たい場合は、入力として $y$ を削ってあげればいいだけです。

Pandas : corrメソッド

PandasのDataFrameに、corrのメソッドが存在して、以下のように計算できます。

import pandas as pd
data = pd.DataFrame({"x":[1,2,3,4,5],
                     "y":[-1, -3, -5, 0, 8]})
data.corr()

ちなみに、このメソッドは他にもいろんな相関係数(スピアマンなど)を計算できて、methodパラメーターで指定することで計算できますが、デフォルトではピアソンの相関係数になっているので、特に気にすることはありません。

■参考


こんなくらいでしょうか。他にもあったり、ミスってたら教えてください。

それでは。