静かなる名辞

pythonとプログラミングのこと

2019/03/22:TechAcademyがteratailの質問・回答を盗用していた件
2019/03/26:TechAcademy盗用事件 公式発表と深まる疑念


pythonで相関係数を計算する方法いろいろ3種類

はじめに

 pythonで相関係数を計算する方法はいろいろあります。確認したら、主要ライブラリだけで3つありました。

 いろいろあるということは用途によって使い分けられるということなので、淡々と書いていきます。

 なお、念のために断っておくと、ここで書いている「相関係数」はすべて「ピアソンの積立相関係数」です。順位相関などはまた別に調べてください(ただしpandasを使う方法だと出せます)。

 目次

データの確認

 予め以下のようなデータを定義しておきます。

>>> import numpy as np
>>> np.random.seed(0)
>>> x = np.arange(0, 10, 0.1)
>>> y = x + np.random.normal(size=x.shape)

 散布図にプロットして確認。

>>> import matplotlib.pyplot as plt
>>> plt.scatter(x, y)
<matplotlib.collections.PathCollection object at 0x7f31aa415f28>
>>> plt.savefig("fig.png")

fig.png
fig.png

 もう少しサンプル数が少なくても良かったような気もしますが、せっかく定義したのでこれでやります。

numpyでやる

 numpyの場合はnp.corrcoefで相関係数「行列」を出してくれます。

>>> np.corrcoef(x, y)
array([[1.        , 0.94129622],
       [0.94129622, 1.        ]])

 0.9以上なので強い相関があるみたいです。「行列」が出てくるので、単に相関係数がほしいときは適当に取り出します。

>>> np.corrcoef(x, y)[0, 1]
0.9412962237004372

 あまりスマートではないので、本当に相関係数「行列」がほしいときに使います。

numpy.corrcoef — NumPy v1.17 Manual

pandasでやる

 pandasでもnumpyと同じことができるようです。

>>> import pandas as pd
>>> df = pd.DataFrame({"x":x, "y":y})
>>> df.corr()
          x         y
x  1.000000  0.941296
y  0.941296  1.000000

 行と列に名前がついて使いやすくなったと思います。また、ピアソン以外の相関係数も、kendall, spearmanをmethod引数に渡すことができ、なんならcallableで任意の関数で計算することもできるといった使いやすさがあります。多機能ですね。

pandas.DataFrame.corr — pandas 0.25.1 documentation


 あと、相関係数「行列」がほしいときはpandasを経由した方が便利でしょうか。seabornに投げて可視化するときに、行・列の名前を考慮してくれるので、便利そうです。

pandas.DataFrameの各列間の相関係数を算出、ヒートマップで可視化 | note.nkmk.me

scipyを使う

 漢は黙ってscipy、という価値観が私にはあります。

>>> from scipy import stats
>>> stats.pearsonr(x, y)
(0.941296223700437, 5.153124094421605e-48)

 勝手に両側検定をやってp値を出してくれています(結果のtupleの0から数えて1つめ)。

scipy.stats.pearsonr — SciPy v1.3.0 Reference Guide

 検定やってくれるのはいいですね。普通は別途やる必要があると思います。

あと思ったこととか

  • なんで標準のstatisticsで用意されてないの
  • statsmodelsは高度な機能はいろいろ提供しているくせに、ただの相関係数の出し方がいくらググっても出てこないのはなんで。リファレンスすごく読みづらいし。あるかもしれないけど諦めた

まとめ

 まあ、3つあればいいか……行列がほしいときは楽そうなのはpandas、単に数字がほしければscipyという使い分けになりそうですね。