単に相関係数というと共分散 \(\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)
]