🎯 상관 관계
| 분석 대상 | 상황 | 추천 도구 |
|---|
| 연속 vs 연속 | 일반적인 선형 관계 | Pearson |
| 이상치 많음 / 순위 데이터 | Spearman / Kendall |
| 비선형 (곡선, 원형 등) | MIC / Distance Corr |
| 범주 vs 연속 | 2개 집단 평균 비교 | T-test / Point-biserial |
| 3개 이상 집단 평균 비교 | ANOVA / Correlation Ratio |
| 범주 vs 범주 | 독립성 확인 및 관계 강도 | Chi-square / Cramer's V |
| 시간 데이터 | 시차가 존재하는 관계 | Cross-Correlation |
| 변수 통제 | 제3의 변수 영향 제거 | Partial Correlation |
▶️ Pearson, Spearman, Kendall
df.corr(method='pearson')
r, p_value = stats.pearsonr(x, y)
from scipy import stats
r, p_value = stats.spearmanr(x, y)
from scipy import stats
tau, p_value = stats.kendalltau(x, y)
| 상관계수( r ) | 해석 (통계적 강도) |
|---|
| 0.0 ~ 0.1 | 거의 없음 |
| 0.1 ~ 0.3 | 약한 상관관계 |
| 0.3 ~ 0.5 | 중간 상관관계 |
| 0.5 ~ 0.7 | 강한 상관관계 |
| 0.7 ~ 1.0 | 매우 강한 상관관계 |
| 켄달 지수(tau) | 해석 |
|---|
| 0.0 ~ 0.2 | 매우 낮음 |
| 0.2 ~ 0.4 | 낮음 ~ 보통 |
| 0.4 ~ 0.6 | 꽤 높음 (중요한 관계) |
| 0.6 이상 | 매우 높음 |
▶️ MIC
from sklearn.feature_selection import mutual_info_regression
mi_score = mutual_info_regression(x.reshape(-1, 1), y)[0]
| 점수 | 해석 |
|---|
| 0.0 | 관계 없음 |
| 0.1 ~ 0.5 | 약한 관계 |
| 0.5 ~ 1.0 | 뚜렷한 관계 |
| 1.0 이상 | 매우 강력한 관계 |
import numpy as np
from sklearn.feature_selection import mutual_info_regression
def simple_mic_alternative(x, y):
x_2d = np.array(x).reshape(-1, 1)
mi = mutual_info_regression(x_2d, y)[0]
normalized_mi = 1 - np.exp(-mi)
return normalized_mi
score = simple_mic_alternative(x, y)
print(f"정규화된 MI 점수 (MIC 대안): {score:.4f}")
▶️ distance_correlation
import dcor
d_corr = dcor.distance_correlation(x, y)
| 점수 | 해석 |
|---|
| 0.0 | 완벽한 독립 |
| 0.1 ~ 0.2 | 매우 약한 관계 |
| 0.2 ~ 0.5 | 중간 정도의 관계 |
| 0.5 ~ 0.8 | 강한 상관관계 |
| 0.8 ~ 1.0 | 매우 강력한 관계 |
▶️ T-test
T-test를 하기전에 만족시킬 조건
- 정규성 검정
- 등분산성 검정
- 알맞는 T-test 진행
1. 정규성 검정
from scipy import stats
W1, p_norm_a = stats.shapiro(group_a)
W2, p_norm_b = stats.shapiro(group_b)
2. 등분산성 검정
from scipy import stats
statistic, p_value = stats.levene(group_a, group_b)
3. 알맞는 T-test 진행
from scipy import stats
result = stats.ttest_ind(group_a, group_b, equal_var=True)
result = stats.ttest_ind(group_a, group_b, equal_var=False)
result = stats.mannwhitneyu(group_a, group_b)
▶️ pointbiserialr
from scipy import stats
r, p_value = stats.pointbiserialr(x, y)
▶️ ANOVA
from scipy import stats
f_stat, p_value = stats.f_oneway(group_A, group_B, group_C)
print(f"F-통계량: {f_stat:.4f}")
print(f"p-value: {p_value:.4f}")
groups = [df['price'][df['book'] == category] for category in df['book'].unique()]
anova_result = stats.f_oneway(*groups)
print(f"ANOVA 검정 결과: F={anova_result.statistic:.4f}, p-value={anova_result.pvalue:.4f}")
▶️ Cramer' V
from scipy.stats.contingency import association
from sklearn import preprocessing
from scipy.stats import chi2_contingency
base_df = df[binary_variable]
base_df = base_df.dropna()
label = preprocessing.LabelEncoder()
data_encoded = pd.DataFrame()
for i in base_df.columns :
data_encoded[i]=label.fit_transform(base_df[i])
def cramers_V(var1,var2) :
crosstab =np.array(pd.crosstab(var1,var2, rownames=None, colnames=None))
stat = chi2_contingency(crosstab)[0]
obs = np.sum(crosstab)
phi2 = stat / obs
r, k = crosstab.shape
phi2corr = max(0, phi2 - (((k-1)*(r-1))/(obs - 1)))
rcorr = r - ((r-1)**2)/(obs-1)
kcorr = k - ((k-1)**2)/(obs-1)
return np.sqrt(phi2corr / min((kcorr-1), (rcorr-1)))
rows= []
for var1 in data_encoded:
col = []
for var2 in data_encoded :
cramers =cramers_V(data_encoded[var1], data_encoded[var2])
col.append(round(cramers,2))
rows.append(col)
cramers_results = np.array(rows)
data_encoded_df = pd.DataFrame(cramers_results, columns = data_encoded.columns, index =data_encoded.columns)
data_encoded_df
▶️ Chi-square
from scipy import stats
contingency_table = pd.crosstab(df[컬럼명1], df[컬럼명2])
chi2, p, dof, expected = stats.chi2_contingency(contingency_table)
| p-value | 해석 |
|---|
| p<0.05 | 우연이 아니다. 둘은 관계가 있다 |
| p>=0.05 | 유의미하지 않음 |