相関比でカテゴリ変数と目的変数の相関の強さを表す

statisticspython

単に相関係数というと共分散 \(\mathrm{Cov}(x,y) = E[(x - \bar{x})(y - \bar{y})]\) と標準偏差 \(\sigma_x = \sqrt{E[(x-\bar{x})^2]}\) で表されるピアソンの積率相関係数のことを指すことが多い。

$$ \rho_{xy} = \frac{\mathrm{Cov}(x,y)}{\sigma_x \sigma_y} $$

ただ、この係数は量的変数同士の線形な相関を表すものなので質的変数であるカテゴリ変数に対しては用いることができない。 質的変数と量的変数の相関は、全変動 \(\Sigma(x-\bar{x})^2\) に対する級間変動 (= 全変動 - 級内変動) の割合である相関比で表すことができる。 0から1までの値を取り1に近いほど相関が強いと言える。例えば全カテゴリの平均値が等しい場合0となり相関がないということになる。

import numpy as np

def correlationRatio(categories, values):
    interclass_variation  = sum([
        (len(values[categories == i]) * ((values[categories == i].mean() - values.mean()) ** 2)).sum() for i in np.unique(categories)
    ])
    total_variation = sum((values - values.mean()) ** 2)
    return interclass_variation / total_variation

実際、ランダムなデータの相関比を出すと 0.012 と小さな値になる。

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

np.random.seed(100)

N=400
df = pd.DataFrame({
    'Team' : np.random.choice(['A', 'B', 'C', 'D'], size=N),
    'Power' : [np.random.normal(loc=50, scale=10) for i in range(N)],
    'Salary' : [np.random.normal(loc=100000, scale=10000) for i in range(N)],
})

_, ax = plt.subplots()
df[df['Team'] == 'A'].plot.scatter(x='Power', y='Salary', color='red', ax=ax)
df[df['Team'] == 'B'].plot.scatter(x='Power', y='Salary', color='green', ax=ax)
df[df['Team'] == 'C'].plot.scatter(x='Power', y='Salary', color='blue', ax=ax)
df[df['Team'] == 'D'].plot.scatter(x='Power', y='Salary', color='purple', ax=ax)

カテゴリごとに平均を変えると 0.811 となり相関があることが分かる。

salaryAveragePerTeam = {
    'A': 80000, 'B': 90000, 'C': 120000, 'D': 130000
}

df['Salary'] = [
    np.random.normal(
        loc=salaryAveragePerTeam[df['Team'][i]], 
        scale=10000
    ) for i in range(N)
]

参考

様々な尺度の変数同士の関係を算出する(Python) - Qiita

相関比の意味と計算方法

第11回 平均値の比較と相関比