Correlation Analysis について
データ分析やモデリングで変数間の関係を調べるためのガイドです。複数の相関手法、結果の解釈、可視化、多重共線性の確認を扱います。
主な機能
- 01Pearson、Spearman、Kendallの手法
- 02カテゴリ変数と非線形の関連
- 03相関の解釈ガイド
- 04ヒートマップと散布図
- 05多重共線性の評価
活用シーン
- 01特徴量間の依存関係の探索
- 02回帰前の予測変数の確認
- 03線形と非線形の関連の比較
- 04相関レポートと可視化の作成
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ aj-geddes/ useful-ai-prompts --skill correlation-analysisインストール後、Claude Code で/correlation-analysisを入力して読み込まれたか確認します。
同梱ファイルscripts/scaffold-analysis.shtemplates/notebook-template.py
詳細
相関分析
概要
相関分析では、変数間の関係の強さと方向を測定し、関連する特徴量の特定や多重共線性の検出に役立てます。
使用する場面
- 数値変数間の関係を特定する
- 回帰モデルの構築前に多重共線性を検出する
- 特徴量間の依存関係を把握するための探索的データ分析
- 特徴量選択と次元削減
- 変数間の関係に関する仮定を検証する
- 線形の関連性と非線形の関連性を比較する
相関の種類
- Pearson:線形相関(連続変数)
- Spearman:順位に基づく相関(順序変数/非線形)
- Kendall:順位相関(堅牢な代替手法)
- Cramér's V:カテゴリ変数間の関連性
- 相互情報量:非線形の依存関係
重要な概念
- 相関係数:-1 から +1 の範囲
- 正の相関:変数が同じ方向に変化する
- 負の相関:変数が反対の方向に変化する
- 多重共線性:予測変数間の高い相関
Python による実装
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.stats import pearsonr, spearmanr, kendalltau
# Sample data
np.random.seed(42)
n = 200
age = np.random.uniform(20, 70, n)
income = age * 2000 + np.random.normal(0, 10000, n)
education_years = age / 2 + np.random.normal(0, 3, n)
satisfaction = income / 50000 + np.random.normal(0, 0.5, n)
df = pd.DataFrame({
'age': age,
'income': income,
'education_years': education_years,
'satisfaction': satisfaction,
'years_employed': age - education_years - 6
})
# Pearson correlation (linear)
corr_matrix = df.corr(method='pearson')
print("Pearson Correlation Matrix:")
print(corr_matrix)
# Individual correlation with p-value
corr_coef, p_value = pearsonr(df['age'], df['income'])
print(f"\nPearson correlation (age vs income): r={corr_coef:.4f}, p-value={p_value:.4f}")
# Spearman correlation (rank-based)
spearman_matrix = df.corr(method='spearman')
print("\nSpearman Correlation Matrix:")
print(spearman_matrix)
spearman_coef, p_value = spearmanr(df['age'], df['income'])
print(f"Spearman correlation (age vs income): rho={spearman_coef:.4f}, p-value={p_value:.4f}")
# Kendall tau correlation
kendall_coef, p_value = kendalltau(df['age'], df['income'])
print(f"Kendall correlation (age vs income): tau={kendall_coef:.4f}, p-value={p_value:.4f}")
# Correlation heatmap
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# Pearson heatmap
sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', center=0,
square=True, ax=axes[0], vmin=-1, vmax=1)
axes[0].set_title('Pearson Correlation Heatmap')
# Spearman heatmap
sns.heatmap(spearman_matrix, annot=True, cmap='coolwarm', center=0,
square=True, ax=axes[1], vmin=-1, vmax=1)
axes[1].set_title('Spearman Correlation Heatmap')
plt.tight_layout()
plt.show()
# Correlation with significance testing
def correlation_with_pvalue(df):
rows, cols = [], []
for col1 in df.columns:
for col2 in df.columns:
if col1 < col2: # Avoid duplicates
r, p = pearsonr(df[col1], df[col2])
rows.append({
'Variable 1': col1,
'Variable 2': col2,
'Correlation': r,
'P-value': p,
'Significant': 'Yes' if p < 0.05 else 'No'
})
return pd.DataFrame(rows)
corr_table = correlation_with_pvalue(df)
print("\nCorrelation with P-values:")
print(corr_table)
# Scatter plots with regression lines
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
pairs = [('age', 'income'), ('age', 'education_years'),
('income', 'satisfaction'), ('education_years', 'years_employed')]
for idx, (var1, var2) in enumerate(pairs):
ax = axes[idx // 2, idx % 2]
ax.scatter(df[var1], df[var2], alpha=0.5)
# Add regression line
z = np.polyfit(df[var1], df[var2], 1)
p = np.poly1d(z)
x_line = np.linspace(df[var1].min(), df[var1].max(), 100)
ax.plot(x_line, p(x_line), "r--", linewidth=2)
r, p_val = pearsonr(df[var1], df[var2])
ax.set_title(f'{var1} vs {var2}\nr={r:.4f}, p={p_val:.4f}')
ax.set_xlabel(var1)
ax.set_ylabel(var2)
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# Multicollinearity detection (VIF)
from statsmodels.stats.outliers_influence import variance_inflation_factor
X = df[['age', 'education_years', 'years_employed']]
vif_data = pd.DataFrame()
vif_data['Variable'] = X.columns
vif_data['VIF'] = [variance_inflation_factor(X.values, i) for i in range(X.shape[1])]
print("\nVariance Inflation Factor (VIF):")
print(vif_data)
print("\nVIF > 10: High multicollinearity")
print("VIF > 5: Moderate multicollinearity")
# Partial correlation (controlling for confounding)
def partial_correlation(df, x, y, control_vars):
from scipy.stats import linregress
# Residuals of x after removing control variables
x_residuals = df[x] - np.poly1d(
np.polyfit(df[control_vars].values, df[x], deg=1)
)(df[control_vars].values)
# Residuals of y after removing control variables
y_residuals = df[y] - np.poly1d(
np.polyfit(df[control_vars].values, df[y], deg=1)
)(df[control_vars].values)
return pearsonr(x_residuals, y_residuals)[0]
partial_corr = partial_correlation(df, 'income', 'satisfaction', ['age'])
print(f"\nPartial correlation (income vs satisfaction, controlling for age): {partial_corr:.4f}")
# Distance correlation (non-linear relationships)
try:
from dcor import distance_correlation
dist_corr = distance_correlation(df['age'], df['income'])
print(f"Distance correlation (age vs income): {dist_corr:.4f}")
except ImportError:
print("dcor library not installed for distance correlation")
# Correlation stability over time
fig, ax = plt.subplots(figsize=(12, 5))
rolling_corr = df['age'].rolling(window=50).corr(df['income'])
ax.plot(rolling_corr.index, rolling_corr.values)
ax.set_title('Rolling Correlation (age vs income, window=50)')
ax.set_ylabel('Correlation Coefficient')
ax.grid(True, alpha=0.3)
plt.show()
解釈のガイドライン
- |r| = 0.0-0.3:弱い相関
- |r| = 0.3-0.7:中程度の相関
- |r| = 0.7-1.0:強い相関
- p < 0.05:統計的に有意
- 高い VIF(>10):多重共線性の問題
重要な注意事項
- 相関 ≠ 因果関係
- Pearson では非線形の関係を捉えられない
- 外れ値は相関を歪める可能性がある
- サンプルサイズは有意性に影響する
- 時間的な傾向によって見せかけの相関が生じることがある
可視化の方法
- 全体像を把握するためのヒートマップ
- 関係を示す散布図
- 多変量分析のためのペアプロット
- 時間とともに変化する関係を示すローリング相関
成果物
- 相関行列(Pearson、Spearman)
- 注釈付き相関ヒートマップ
- 統計的有意性の表
- 回帰直線付き散布図
- 多重共線性の評価(VIF)
- 偏相関分析
- 関係性の解釈レポート
コメント
Markdown 対応