相関係数はどう選ぶ?
Pearson と Spearman

2つの量の関係の強さを1つの数で表すのが相関係数です。代表的な2種類のうち、どちらを使えばよいかは「データの形」で決まります。7つの事例で、散布図を見て自分で選び、答え合わせをしてみましょう。

Pearson の相関係数 r

  • データの値そのものを使って計算します。
  • 「点がどれだけ1本の直線に沿っているか」を表します。
  • 外れ値(飛び離れた値)に引っぱられやすい性質があります。
  • r が 0 と違うかを検定したり区間推定したりするときは、データが正規分布に従うことが前提です。

Spearman の順位相関係数 ρ(ロー)

  • 値を「小さい順の順位」に置き換えてから、Pearson と同じ計算をします。
  • 「一方が増えるともう一方も増え続けるか(単調か)」を表します。曲線でもかまいません。
  • 順位しか使わないので、外れ値の影響を受けにくくなります。
  • 正規分布を前提にしません。5段階評価や順位のデータにも使えます。

選び方の手順

  1. 散布図を描く。U字のように途中で向きが変わる関係なら、どちらの相関係数も向きません。
  2. データの種類を確かめる。5段階評価や順位のような「順番だけに意味がある」データなら Spearman を使います。
  3. 外れ値がないか見る。飛び離れた点があれば Spearman が安全です。
  4. 正規分布に近いか確かめる。ヒストグラムや Q-Q プロット、正規性の検定で確認し、問題がなければ Pearson、崩れていれば Spearman を使います。

データはこの画面の中で乱数から作っています。設定を変えても回答は残ります。

事例を選ぶ

全部の事例をくらべる

r と ρ を −1 から +1 の線の上に並べました。2つの印が離れているほど、2つの係数の答えが食い違っています。

用語のまとめ

相関係数
2つの量の関係の強さを −1〜+1 で表した数。+1 に近いほど「一方が大きいともう一方も大きい」、0 に近いほど関係が弱いことを表します。
順位
値を小さい順に並べたときの番号。同じ値が複数あるときは順位の平均を使います(例:2位と3位が同じ値なら、どちらも 2.5 位)。
単調な関係
一方が増えるとき、もう一方が増え続ける(または減り続ける)関係。直線でなくてもかまいません。
正規分布
平均を中心に左右対称な釣り鐘型の分布。身長のように多くの要因が少しずつ積み重なる量はこの形に近くなります。
Q-Q プロット
データを正規分布と比べる図。点が破線に沿って並べば正規分布に近く、端が破線から大きく反れていれば正規分布から外れています。
正規性の検定
「データは正規分布に従う」という仮説を確かめる検定。ここでは Shapiro–Wilk 検定を使い、p 値が 0.05 より小さければ「正規分布とは言いにくい」と判断します。データが少ないとずれを見逃しやすく、多いとわずかなずれでも p 値が小さくなる点に注意します。
外れ値
ほかのデータから大きく飛び離れた値。入力ミスのこともあれば、性質の違う対象が混ざっていることもあります。

Python で確かめる

授業で使っている SciPy でも同じ確認ができます。フォントは、このコードと同じフォルダに置いた NotoSansJP-Regular.ttf と NotoSansJP-Bold.ttf を使います。

コードを表示する
from pathlib import Path
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import font_manager as fm
from scipy import stats

# 日本語フォントの設定(同じフォルダの Noto Sans JP を使う)
try:
    base = Path(__file__).parent      # .py ファイルとして実行したとき
except NameError:
    base = Path.cwd()                 # Jupyter Notebook で実行したとき
for f in ["NotoSansJP-Regular.ttf", "NotoSansJP-Bold.ttf"]:
    fm.fontManager.addfont(str(base / f))
plt.rcParams["font.family"] = fm.FontProperties(
    fname=str(base / "NotoSansJP-Regular.ttf")).get_name()

# データの準備(配信週数と再生回数:単調だが直線ではない例)
rng = np.random.default_rng(0)
x = rng.uniform(0, 10, 40)
y = np.exp(0.5 * x + rng.normal(0, 0.3, 40))

# 1. 散布図と、分布の形(Q-Q プロット)を見る
fig, ax = plt.subplots(1, 3, figsize=(11, 3.4))
ax[0].scatter(x, y)
ax[0].set_xlabel("配信開始からの週数")
ax[0].set_ylabel("週間再生回数(千回)")
ax[0].set_title("散布図")
stats.probplot(x, plot=ax[1]); ax[1].set_title("x の Q-Q プロット")
stats.probplot(y, plot=ax[2]); ax[2].set_title("y の Q-Q プロット")
plt.tight_layout()
plt.show()

# 2. 正規性の検定(p < 0.05 なら正規分布とは言いにくい)
print("x の正規性:", stats.shapiro(x))
print("y の正規性:", stats.shapiro(y))

# 3. 2つの相関係数をくらべる
print("Pearson  r =", stats.pearsonr(x, y))
print("Spearman ρ =", stats.spearmanr(x, y))