はじめに
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")
もう少しサンプル数が少なくても良かったような気もしますが、せっかく定義したのでこれでやります。
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
あまりスマートではないので、本当に相関係数「行列」がほしいときに使います。
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に投げて可視化するときに、行・列の名前を考慮してくれるので、便利そうです。
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という使い分けになりそうですね。