Skip to Content

๊ฐ€์„ค๊ฒ€์ • (Hypothesis Testing)

์ค‘๊ธ‰์ˆ˜ํ•™/ํ†ต๊ณ„

0. ์‚ฌ์ „ ์ค€๋น„ (Setup)

๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ์…‹์„ ํ™œ์šฉํ•˜์—ฌ ๊ฐ€์„ค๊ฒ€์ •์„ ์‹ค์Šตํ•ฉ๋‹ˆ๋‹ค.

import pandas as pd import numpy as np import seaborn as sns import matplotlib.pyplot as plt from scipy import stats from scipy.stats import ( ttest_ind, ttest_rel, ttest_1samp, mannwhitneyu, wilcoxon, kruskal, chi2_contingency, fisher_exact, f_oneway, shapiro, levene, bartlett, spearmanr, pearsonr, kendalltau, kstest, normaltest, anderson ) import warnings warnings.filterwarnings('ignore') # 1. Titanic Dataset titanic = sns.load_dataset('titanic') print(f"Titanic: {titanic.shape}") # 2. Iris Dataset iris = sns.load_dataset('iris') print(f"Iris: {iris.shape}") # 3. Tips Dataset tips = sns.load_dataset('tips') print(f"Tips: {tips.shape}") # 4. Diamonds Dataset (์ƒ˜ํ”Œ๋ง) diamonds = sns.load_dataset('diamonds').sample(n=1000, random_state=42) print(f"Diamonds: {diamonds.shape}")
์‹คํ–‰ ๊ฒฐ๊ณผ
Titanic: (891, 15)
Iris: (150, 5)
Tips: (244, 7)
Diamonds: (1000, 10)

1. ๊ฐ€์„ค๊ฒ€์ •์˜ ๊ธฐ์ดˆ

ํ•ต์‹ฌ ๊ฐœ๋…

์šฉ์–ด์„ค๋ช…
๊ท€๋ฌด๊ฐ€์„ค (Hโ‚€)โ€œ์ฐจ์ด/ํšจ๊ณผ๊ฐ€ ์—†๋‹คโ€ - ๊ธฐ๋ณธ ๊ฐ€์ •
๋Œ€๋ฆฝ๊ฐ€์„ค (Hโ‚)โ€œ์ฐจ์ด/ํšจ๊ณผ๊ฐ€ ์žˆ๋‹คโ€ - ์ฆ๋ช…ํ•˜๊ณ  ์‹ถ์€ ๊ฒƒ
p-value๊ท€๋ฌด๊ฐ€์„ค์ด ์ฐธ์ผ ๋•Œ, ํ˜„์žฌ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ฌ ํ™•๋ฅ 
์œ ์˜์ˆ˜์ค€ (ฮฑ)๋ณดํ†ต 0.05 (5%) ์‚ฌ์šฉ
๊ฒ€์ •๋ ฅ (Power)์‹ค์ œ ํšจ๊ณผ๊ฐ€ ์žˆ์„ ๋•Œ ์ด๋ฅผ ํƒ์ง€ํ•  ํ™•๋ฅ 

๊ฒ€์ • ์„ ํƒ ๊ฐ€์ด๋“œ

๋ฐ์ดํ„ฐ ์œ ํ˜•? โ”œโ”€โ”€ ์—ฐ์†ํ˜• (Continuous) โ”‚ โ”œโ”€โ”€ ์ •๊ทœ๋ถ„ํฌ โ†’ ๋ชจ์ˆ˜์  ๊ฒ€์ • (t-test, ANOVA) โ”‚ โ””โ”€โ”€ ๋น„์ •๊ทœ๋ถ„ํฌ โ†’ ๋น„๋ชจ์ˆ˜์  ๊ฒ€์ • (Mann-Whitney, Kruskal-Wallis) โ”‚ โ””โ”€โ”€ ๋ฒ”์ฃผํ˜• (Categorical) โ”œโ”€โ”€ 2ร—2 ํ‘œ (์†Œํ‘œ๋ณธ) โ†’ Fisher's Exact Test โ””โ”€โ”€ ๊ทธ ์™ธ โ†’ Chi-Square Test

2. ์ •๊ทœ์„ฑ ๊ฒ€์ • (Normality Tests)

๐ŸŽฏ ์–ธ์ œ ์‚ฌ์šฉํ•˜๋‚˜์š”?

t-๊ฒ€์ •, ANOVA ๊ฐ™์€ ๋ชจ์ˆ˜์  ๊ฒ€์ •์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์ „์— ๋ฐ์ดํ„ฐ๊ฐ€ ์ •๊ทœ๋ถ„ํฌ๋ฅผ ๋”ฐ๋ฅด๋Š”์ง€ ํ™•์ธํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ •๊ทœ์„ฑ์ด ๋งŒ์กฑ๋˜์ง€ ์•Š์œผ๋ฉด ๋น„๋ชจ์ˆ˜์  ๊ฒ€์ •(Mann-Whitney, Kruskal-Wallis ๋“ฑ)์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Shapiro-Wilk Test

๐Ÿ“Œ ์‚ฌ์šฉ ์ƒํ™ฉ ์˜ˆ์‹œ

  • ์‹ ์•ฝ ์ž„์ƒ์‹œํ—˜์—์„œ ํ˜ˆ์•• ์ธก์ •๊ฐ’์ด ์ •๊ทœ๋ถ„ํฌ๋ฅผ ๋”ฐ๋ฅด๋Š”์ง€ ํ™•์ธ
  • A/B ํ…Œ์ŠคํŠธ ์ „, ์‚ฌ์šฉ์ž ์ฒด๋ฅ˜ ์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ์˜ ๋ถ„ํฌ ํ™•์ธ
  • ์ œ์กฐ ๊ณต์ •์—์„œ ์ œํ’ˆ ๋ฌด๊ฒŒ ๋ฐ์ดํ„ฐ๊ฐ€ ์ •์ƒ ๋ถ„ํฌ์ธ์ง€ ํ’ˆ์งˆ ๊ฒ€์‚ฌ

๐Ÿ’ก ํŠน์ง•: ๊ฐ€์žฅ ๊ฒ€์ •๋ ฅ์ด ๋†’์€ ์ •๊ทœ์„ฑ ๊ฒ€์ •. ๋‹จ, n < 5000์ผ ๋•Œ ์‚ฌ์šฉ ๊ถŒ์žฅ.

# Titanic: ๋‚˜์ด ๋ถ„ํฌ์˜ ์ •๊ทœ์„ฑ ๊ฒ€์ • ages = titanic['age'].dropna() stat, p_value = shapiro(ages) print("=== Shapiro-Wilk ์ •๊ทœ์„ฑ ๊ฒ€์ • ===") print(f"๋ฐ์ดํ„ฐ: Titanic ์Šน๊ฐ ๋‚˜์ด (n={len(ages)})") print(f"ํ†ต๊ณ„๋Ÿ‰: {stat:.4f}") print(f"p-value: {p_value:.4f}") print(f"๊ฒฐ๋ก : {'์ •๊ทœ๋ถ„ํฌ๋ฅผ ๋”ฐ๋ฆ„ โœ“' if p_value >= 0.05 else '์ •๊ทœ๋ถ„ํฌ๋ฅผ ๋”ฐ๋ฅด์ง€ ์•Š์Œ โœ—'}") # ์‹œ๊ฐํ™” fig, axes = plt.subplots(1, 2, figsize=(10, 4)) axes[0].hist(ages, bins=30, edgecolor='black', alpha=0.7) axes[0].set_title('Age Distribution') axes[0].set_xlabel('Age') stats.probplot(ages, dist="norm", plot=axes[1]) axes[1].set_title('Q-Q Plot') plt.tight_layout() plt.show()
์‹คํ–‰ ๊ฒฐ๊ณผ
=== Shapiro-Wilk ์ •๊ทœ์„ฑ ๊ฒ€์ • ===
๋ฐ์ดํ„ฐ: Titanic ์Šน๊ฐ ๋‚˜์ด (n=714)
ํ†ต๊ณ„๋Ÿ‰: 0.9816
p-value: 0.0000
๊ฒฐ๋ก : ์ •๊ทœ๋ถ„ํฌ๋ฅผ ๋”ฐ๋ฅด์ง€ ์•Š์Œ โœ—

Dโ€™Agostino-Pearson Test

๐Ÿ“Œ ์‚ฌ์šฉ ์ƒํ™ฉ ์˜ˆ์‹œ

  • ๊ธˆ์œต ๋ฐ์ดํ„ฐ์˜ ์ˆ˜์ต๋ฅ  ๋ถ„ํฌ๊ฐ€ ์ •๊ทœ๋ถ„ํฌ์ธ์ง€ ํ™•์ธ (์™œ๋„/์ฒจ๋„๊ฐ€ ์ค‘์š”ํ•œ ๊ฒฝ์šฐ)
  • ์„ค๋ฌธ์กฐ์‚ฌ ์ ์ˆ˜์˜ ๋ถ„ํฌ ํ˜•ํƒœ ๊ฒ€์ •
  • ์‹œํ—˜ ์ ์ˆ˜ ๋ถ„ํฌ์˜ ๋น„๋Œ€์นญ์„ฑ ํ™•์ธ

๐Ÿ’ก ํŠน์ง•: **์™œ๋„(skewness)์™€ ์ฒจ๋„(kurtosis)**๋ฅผ ํ•จ๊ป˜ ๊ณ ๋ ค. ๋ถ„ํฌ์˜ ํ˜•ํƒœ๊ฐ€ ์ค‘์š”ํ•  ๋•Œ ์œ ์šฉ. n โ‰ฅ 20์ผ ๋•Œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ.

# Iris: ๊ฝƒ์žŽ ๊ธธ์ด์˜ ์ •๊ทœ์„ฑ ๊ฒ€์ • petal_length = iris['petal_length'] stat, p_value = normaltest(petal_length) print("=== D'Agostino-Pearson ์ •๊ทœ์„ฑ ๊ฒ€์ • ===") print(f"๋ฐ์ดํ„ฐ: Iris ๊ฝƒ์žŽ ๊ธธ์ด (n={len(petal_length)})") print(f"ํ†ต๊ณ„๋Ÿ‰: {stat:.4f}") print(f"p-value: {p_value:.4f}") print(f"๊ฒฐ๋ก : {'์ •๊ทœ๋ถ„ํฌ๋ฅผ ๋”ฐ๋ฆ„ โœ“' if p_value >= 0.05 else '์ •๊ทœ๋ถ„ํฌ๋ฅผ ๋”ฐ๋ฅด์ง€ ์•Š์Œ โœ—'}")
์‹คํ–‰ ๊ฒฐ๊ณผ
=== D'Agostino-Pearson ์ •๊ทœ์„ฑ ๊ฒ€์ • ===
๋ฐ์ดํ„ฐ: Iris ๊ฝƒ์žŽ ๊ธธ์ด (n=150)
ํ†ต๊ณ„๋Ÿ‰: 31.5324
p-value: 0.0000
๊ฒฐ๋ก : ์ •๊ทœ๋ถ„ํฌ๋ฅผ ๋”ฐ๋ฅด์ง€ ์•Š์Œ โœ—

Kolmogorov-Smirnov Test

๐Ÿ“Œ ์‚ฌ์šฉ ์ƒํ™ฉ ์˜ˆ์‹œ

  • ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ(n > 5000)์˜ ์ •๊ทœ์„ฑ ๊ฒ€์ •
  • ์ •๊ทœ๋ถ„ํฌ ์™ธ์— ๋‹ค๋ฅธ ์ด๋ก ์  ๋ถ„ํฌ(์ง€์ˆ˜๋ถ„ํฌ, ๊ท ๋“ฑ๋ถ„ํฌ ๋“ฑ)์™€ ๋น„๊ต
  • ๋‘ ํ‘œ๋ณธ์˜ ๋ถ„ํฌ๊ฐ€ ๋™์ผํ•œ์ง€ ๋น„๊ต (2-sample KS test)

๐Ÿ’ก ํŠน์ง•: ํ‘œ๋ณธ ํฌ๊ธฐ์— ๋œ ๋ฏผ๊ฐํ•˜์—ฌ ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ์— ์ ํ•ฉ. ๋‹ค์–‘ํ•œ ๋ถ„ํฌ์™€ ๋น„๊ต ๊ฐ€๋Šฅ.

# Tips: ํŒ ๊ธˆ์•ก์˜ ์ •๊ทœ์„ฑ ๊ฒ€์ • tip_values = tips['tip'] # ํ‘œ์ค€ํ™” ํ›„ ๊ฒ€์ • tip_standardized = (tip_values - tip_values.mean()) / tip_values.std() stat, p_value = kstest(tip_standardized, 'norm') print("=== Kolmogorov-Smirnov ์ •๊ทœ์„ฑ ๊ฒ€์ • ===") print(f"๋ฐ์ดํ„ฐ: Tips ํŒ ๊ธˆ์•ก (n={len(tip_values)})") print(f"ํ†ต๊ณ„๋Ÿ‰: {stat:.4f}") print(f"p-value: {p_value:.4f}") print(f"๊ฒฐ๋ก : {'์ •๊ทœ๋ถ„ํฌ๋ฅผ ๋”ฐ๋ฆ„ โœ“' if p_value >= 0.05 else '์ •๊ทœ๋ถ„ํฌ๋ฅผ ๋”ฐ๋ฅด์ง€ ์•Š์Œ โœ—'}")
์‹คํ–‰ ๊ฒฐ๊ณผ
=== Kolmogorov-Smirnov ์ •๊ทœ์„ฑ ๊ฒ€์ • ===
๋ฐ์ดํ„ฐ: Tips ํŒ ๊ธˆ์•ก (n=244)
ํ†ต๊ณ„๋Ÿ‰: 0.0975
p-value: 0.0186
๊ฒฐ๋ก : ์ •๊ทœ๋ถ„ํฌ๋ฅผ ๋”ฐ๋ฅด์ง€ ์•Š์Œ โœ—

Anderson-Darling Test

๐Ÿ“Œ ์‚ฌ์šฉ ์ƒํ™ฉ ์˜ˆ์‹œ

  • ๊ทน๋‹จ๊ฐ’(์ด์ƒ์น˜)์ด ์ค‘์š”ํ•œ ๋ถ„์„์—์„œ ์ •๊ทœ์„ฑ ํ™•์ธ (์œ„ํ—˜ ๊ด€๋ฆฌ, ๋ณดํ—˜ ๋“ฑ)
  • ๋ถ„ํฌ์˜ ๊ผฌ๋ฆฌ ๋ถ€๋ถ„์ด ์ •๊ทœ๋ถ„ํฌ์™€ ์–ผ๋งˆ๋‚˜ ๋‹ค๋ฅธ์ง€ ํ™•์ธ
  • ์—ฌ๋Ÿฌ ์œ ์˜์ˆ˜์ค€์—์„œ ๋™์‹œ์— ํŒ๋‹จ์ด ํ•„์š”ํ•  ๋•Œ

๐Ÿ’ก ํŠน์ง•: ๋ถ„ํฌ์˜ ๊ผฌ๋ฆฌ(tail) ๋ถ€๋ถ„์— ๋” ๋ฏผ๊ฐ. ๊ทน๋‹จ๊ฐ’์ด ์ค‘์š”ํ•œ ๊ธˆ์œต/๋ณดํ—˜ ๋ถ„์•ผ์—์„œ ์„ ํ˜ธ.

# Diamonds: ๊ฐ€๊ฒฉ์˜ ์ •๊ทœ์„ฑ ๊ฒ€์ • prices = diamonds['price'] result = anderson(prices, dist='norm') print("=== Anderson-Darling ์ •๊ทœ์„ฑ ๊ฒ€์ • ===") print(f"๋ฐ์ดํ„ฐ: Diamonds ๊ฐ€๊ฒฉ (n={len(prices)})") print(f"ํ†ต๊ณ„๋Ÿ‰: {result.statistic:.4f}") print("\n์œ ์˜์ˆ˜์ค€๋ณ„ ์ž„๊ณ„๊ฐ’:") for i, (cv, sl) in enumerate(zip(result.critical_values, result.significance_level)): result_str = "๊ธฐ๊ฐ" if result.statistic > cv else "์ฑ„ํƒ" print(f" {sl}%: ์ž„๊ณ„๊ฐ’ = {cv:.4f} โ†’ Hโ‚€ {result_str}")
์‹คํ–‰ ๊ฒฐ๊ณผ
=== Anderson-Darling ์ •๊ทœ์„ฑ ๊ฒ€์ • ===
๋ฐ์ดํ„ฐ: Diamonds ๊ฐ€๊ฒฉ (n=1000)
ํ†ต๊ณ„๋Ÿ‰: 47.8932

์œ ์˜์ˆ˜์ค€๋ณ„ ์ž„๊ณ„๊ฐ’:
15.0%: ์ž„๊ณ„๊ฐ’ = 0.5740 โ†’ Hโ‚€ ๊ธฐ๊ฐ
10.0%: ์ž„๊ณ„๊ฐ’ = 0.6540 โ†’ Hโ‚€ ๊ธฐ๊ฐ
5.0%: ์ž„๊ณ„๊ฐ’ = 0.7850 โ†’ Hโ‚€ ๊ธฐ๊ฐ
2.5%: ์ž„๊ณ„๊ฐ’ = 0.9150 โ†’ Hโ‚€ ๊ธฐ๊ฐ
1.0%: ์ž„๊ณ„๊ฐ’ = 1.0890 โ†’ Hโ‚€ ๊ธฐ๊ฐ

3. ๋“ฑ๋ถ„์‚ฐ ๊ฒ€์ • (Homogeneity of Variance)

๐ŸŽฏ ์–ธ์ œ ์‚ฌ์šฉํ•˜๋‚˜์š”?

๋…๋ฆฝํ‘œ๋ณธ t-๊ฒ€์ •์ด๋‚˜ ANOVA๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์ „, ๋น„๊ตํ•˜๋ ค๋Š” ๊ทธ๋ฃน๋“ค์˜ ๋ถ„์‚ฐ์ด ๋™์ผํ•œ์ง€ ํ™•์ธํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋“ฑ๋ถ„์‚ฐ ๊ฐ€์ •์ด ์œ„๋ฐฐ๋˜๋ฉด Welchโ€™s t-test๋‚˜ Games-Howell ์‚ฌํ›„๊ฒ€์ •์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Leveneโ€™s Test

๐Ÿ“Œ ์‚ฌ์šฉ ์ƒํ™ฉ ์˜ˆ์‹œ

  • A/B ํ…Œ์ŠคํŠธ์—์„œ ์‹คํ—˜๊ตฐ๊ณผ ๋Œ€์กฐ๊ตฐ์˜ ๊ตฌ๋งค๊ธˆ์•ก ๋ถ„์‚ฐ์ด ๊ฐ™์€์ง€ ํ™•์ธ
  • ๋‚จ๋…€ ๊ทธ๋ฃน์˜ ์‹œํ—˜ ์ ์ˆ˜ ๋ถ„์‚ฐ์ด ๋™์ผํ•œ์ง€ ๊ฒ€์ •
  • ์—ฌ๋Ÿฌ ๊ณต์žฅ์—์„œ ์ƒ์‚ฐ๋œ ์ œํ’ˆ ํ’ˆ์งˆ์˜ ์‚ฐํฌ๋„๊ฐ€ ๋™์ผํ•œ์ง€ ํ™•์ธ

๐Ÿ’ก ํŠน์ง•: ์ •๊ทœ์„ฑ ๊ฐ€์ •์ด ํ•„์š” ์—†์–ด ๋กœ๋ฒ„์ŠคํŠธํ•จ. ๋น„์ •๊ทœ ๋ฐ์ดํ„ฐ์—์„œ๋„ ์‚ฌ์šฉ ๊ฐ€๋Šฅ.

# Titanic: ์ƒ์กด ์—ฌ๋ถ€์— ๋”ฐ๋ฅธ ๋‚˜์ด ๋ถ„์‚ฐ ๋น„๊ต survived_ages = titanic[titanic['survived'] == 1]['age'].dropna() died_ages = titanic[titanic['survived'] == 0]['age'].dropna() stat, p_value = levene(survived_ages, died_ages) print("=== Levene's ๋“ฑ๋ถ„์‚ฐ ๊ฒ€์ • ===") print(f"์ƒ์กด์ž ๋‚˜์ด ๋ถ„์‚ฐ: {survived_ages.var():.2f}") print(f"์‚ฌ๋ง์ž ๋‚˜์ด ๋ถ„์‚ฐ: {died_ages.var():.2f}") print(f"ํ†ต๊ณ„๋Ÿ‰: {stat:.4f}") print(f"p-value: {p_value:.4f}") print(f"๊ฒฐ๋ก : {'๋“ฑ๋ถ„์‚ฐ ๊ฐ€์ • ์ถฉ์กฑ โœ“' if p_value >= 0.05 else '๋“ฑ๋ถ„์‚ฐ ๊ฐ€์ • ๋ถˆ์ถฉ์กฑ โœ—'}")
์‹คํ–‰ ๊ฒฐ๊ณผ
=== Levene's ๋“ฑ๋ถ„์‚ฐ ๊ฒ€์ • ===
์ƒ์กด์ž ๋‚˜์ด ๋ถ„์‚ฐ: 207.03
์‚ฌ๋ง์ž ๋‚˜์ด ๋ถ„์‚ฐ: 199.41
ํ†ต๊ณ„๋Ÿ‰: 0.1557
p-value: 0.6933
๊ฒฐ๋ก : ๋“ฑ๋ถ„์‚ฐ ๊ฐ€์ • ์ถฉ์กฑ โœ“

Bartlettโ€™s Test

๐Ÿ“Œ ์‚ฌ์šฉ ์ƒํ™ฉ ์˜ˆ์‹œ

  • ์ •๊ทœ๋ถ„ํฌ๊ฐ€ ํ™•์ธ๋œ ๋ฐ์ดํ„ฐ์—์„œ ๊ทธ๋ฃน ๊ฐ„ ๋ถ„์‚ฐ ๋น„๊ต
  • ์ž„์ƒ์‹œํ—˜์—์„œ ์—ฌ๋Ÿฌ ์šฉ๋Ÿ‰ ๊ทธ๋ฃน์˜ ๋ฐ˜์‘ ๋ณ€๋™์„ฑ ๋น„๊ต
  • ํ’ˆ์งˆ ๊ด€๋ฆฌ์—์„œ ์—ฌ๋Ÿฌ ์ƒ์‚ฐ ๋ผ์ธ์˜ ๋ถ„์‚ฐ ๋™์ผ์„ฑ ๊ฒ€์ •

๐Ÿ’ก ํŠน์ง•: ์ •๊ทœ๋ถ„ํฌ๋ฅผ ๋”ฐ๋ฅผ ๋•Œ ๊ฐ€์žฅ ๊ฐ•๋ ฅํ•œ ๋“ฑ๋ถ„์‚ฐ ๊ฒ€์ •. ์ •๊ทœ์„ฑ์ด ์œ„๋ฐฐ๋˜๋ฉด Levene ์‚ฌ์šฉ ๊ถŒ์žฅ.

# Iris: ํ’ˆ์ข…๋ณ„ ๊ฝƒ๋ฐ›์นจ ๊ธธ์ด ๋ถ„์‚ฐ ๋น„๊ต setosa = iris[iris['species'] == 'setosa']['sepal_length'] versicolor = iris[iris['species'] == 'versicolor']['sepal_length'] virginica = iris[iris['species'] == 'virginica']['sepal_length'] stat, p_value = bartlett(setosa, versicolor, virginica) print("=== Bartlett's ๋“ฑ๋ถ„์‚ฐ ๊ฒ€์ • ===") print(f"Setosa ๋ถ„์‚ฐ: {setosa.var():.4f}") print(f"Versicolor ๋ถ„์‚ฐ: {versicolor.var():.4f}") print(f"Virginica ๋ถ„์‚ฐ: {virginica.var():.4f}") print(f"ํ†ต๊ณ„๋Ÿ‰: {stat:.4f}") print(f"p-value: {p_value:.4f}") print(f"๊ฒฐ๋ก : {'๋“ฑ๋ถ„์‚ฐ ๊ฐ€์ • ์ถฉ์กฑ โœ“' if p_value >= 0.05 else '๋“ฑ๋ถ„์‚ฐ ๊ฐ€์ • ๋ถˆ์ถฉ์กฑ โœ—'}")
์‹คํ–‰ ๊ฒฐ๊ณผ
=== Bartlett's ๋“ฑ๋ถ„์‚ฐ ๊ฒ€์ • ===
Setosa ๋ถ„์‚ฐ: 0.1242
Versicolor ๋ถ„์‚ฐ: 0.2664
Virginica ๋ถ„์‚ฐ: 0.4043
ํ†ต๊ณ„๋Ÿ‰: 16.0057
p-value: 0.0003
๊ฒฐ๋ก : ๋“ฑ๋ถ„์‚ฐ ๊ฐ€์ • ๋ถˆ์ถฉ์กฑ โœ—

4. T-๊ฒ€์ • (T-Tests)

๋‹จ์ผํ‘œ๋ณธ t-๊ฒ€์ • (One-Sample T-Test)

๐Ÿ“Œ ์‚ฌ์šฉ ์ƒํ™ฉ ์˜ˆ์‹œ

  • ํ’ˆ์งˆ ๊ฒ€์‚ฌ: ๊ณต์žฅ์—์„œ ์ƒ์‚ฐ๋œ ๋ฐฐํ„ฐ๋ฆฌ ํ‰๊ท  ์ˆ˜๋ช…์ด ๊ณต์นญ ์ˆ˜๋ช… 1000์‹œ๊ฐ„๊ณผ ๊ฐ™์€์ง€ ๊ฒ€์ฆ
  • ๋งˆ์ผ€ํŒ…: ๊ณ ๊ฐ ํ‰๊ท  ๋งŒ์กฑ๋„๊ฐ€ ๋ชฉํ‘œ์น˜ 4.0์ ์— ๋„๋‹ฌํ–ˆ๋Š”์ง€ ํ™•์ธ
  • ๊ต์œก: ํ•™์ƒ๋“ค์˜ ํ‰๊ท  ์ ์ˆ˜๊ฐ€ ์ „๊ตญ ํ‰๊ท  75์ ๊ณผ ๋‹ค๋ฅธ์ง€ ๊ฒ€์ •
  • ์„œ๋น„์Šค: ํ‰๊ท  ์‘๋‹ต ์‹œ๊ฐ„์ด SLA ๊ธฐ์ค€ 3์ดˆ ์ด๋‚ด์ธ์ง€ ํ™•์ธ

๐Ÿ’ก ํ•ต์‹ฌ ์งˆ๋ฌธ: โ€œ์šฐ๋ฆฌ ํ‘œ๋ณธ์˜ ํ‰๊ท ์ด ํŠน์ • ๊ธฐ์ค€๊ฐ’๊ณผ ๊ฐ™์€๊ฐ€/๋‹ค๋ฅธ๊ฐ€?โ€

# Tips: ํ‰๊ท  ํŒ์ด $3์ธ์ง€ ๊ฒ€์ • # ์ƒํ™ฉ: ๋ ˆ์Šคํ† ๋ž‘ ๋งค๋‹ˆ์ €๊ฐ€ "์šฐ๋ฆฌ ๊ฐ€๊ฒŒ ํ‰๊ท  ํŒ์€ $3์ด๋‹ค"๋ผ๊ณ  ์ฃผ์žฅ. ์ด๊ฒŒ ๋งž๋Š”์ง€ ๊ฒ€์ฆ. tip_values = tips['tip'] hypothesized_mean = 3.0 stat, p_value = ttest_1samp(tip_values, hypothesized_mean) print("=== ๋‹จ์ผํ‘œ๋ณธ t-๊ฒ€์ • ===") print(f"Hโ‚€: ํ‰๊ท  ํŒ = ${hypothesized_mean:.2f}") print(f"Hโ‚: ํ‰๊ท  ํŒ โ‰  ${hypothesized_mean:.2f}") print(f"\nํ‘œ๋ณธ ํ‰๊ท : ${tip_values.mean():.2f}") print(f"ํ‘œ๋ณธ ํ‘œ์ค€ํŽธ์ฐจ: ${tip_values.std():.2f}") print(f"t-ํ†ต๊ณ„๋Ÿ‰: {stat:.4f}") print(f"p-value: {p_value:.4f}") print(f"\n๊ฒฐ๋ก : {'ํ‰๊ท  ํŒ์€ $3์™€ ๋‹ค๋ฆ„' if p_value < 0.05 else 'ํ‰๊ท  ํŒ์€ $3์™€ ๊ฐ™๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ์Œ'}")
์‹คํ–‰ ๊ฒฐ๊ณผ
=== ๋‹จ์ผํ‘œ๋ณธ t-๊ฒ€์ • ===
Hโ‚€: ํ‰๊ท  ํŒ = $3.00
Hโ‚: ํ‰๊ท  ํŒ โ‰  $3.00

ํ‘œ๋ณธ ํ‰๊ท : $3.00
ํ‘œ๋ณธ ํ‘œ์ค€ํŽธ์ฐจ: $1.38
t-ํ†ต๊ณ„๋Ÿ‰: -0.0363
p-value: 0.9711

๊ฒฐ๋ก : ํ‰๊ท  ํŒ์€ $3์™€ ๊ฐ™๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ์Œ

๋…๋ฆฝํ‘œ๋ณธ t-๊ฒ€์ • (Independent Samples T-Test)

๐Ÿ“Œ ์‚ฌ์šฉ ์ƒํ™ฉ ์˜ˆ์‹œ

  • A/B ํ…Œ์ŠคํŠธ: ์ƒˆ ์›น์‚ฌ์ดํŠธ ๋””์ž์ธ(B)์ด ๊ธฐ์กด ๋””์ž์ธ(A)๋ณด๋‹ค ์ „ํ™˜์œจ์ด ๋†’์€์ง€ ๊ฒ€์ฆ
  • ์˜ํ•™: ์‹ ์•ฝ ํˆฌ์—ฌ๊ตฐ๊ณผ ์œ„์•ฝ๊ตฐ์˜ ํ˜ˆ์•• ๋ณ€ํ™” ๋น„๊ต
  • ๊ต์œก: ์˜จ๋ผ์ธ ์ˆ˜์—…๊ณผ ์˜คํ”„๋ผ์ธ ์ˆ˜์—…์˜ ์„ฑ์  ์ฐจ์ด ๋น„๊ต
  • HR: ์žฌํƒ๊ทผ๋ฌด์ž์™€ ์‚ฌ๋ฌด์‹ค ๊ทผ๋ฌด์ž์˜ ์ƒ์‚ฐ์„ฑ ์ฐจ์ด ๋ถ„์„
  • ๋งˆ์ผ€ํŒ…: ๋‚จ์„ฑ ๊ณ ๊ฐ๊ณผ ์—ฌ์„ฑ ๊ณ ๊ฐ์˜ ํ‰๊ท  ๊ตฌ๋งค ๊ธˆ์•ก ๋น„๊ต

๐Ÿ’ก ํ•ต์‹ฌ ์งˆ๋ฌธ: โ€œ์„œ๋กœ ๋‹ค๋ฅธ ๋‘ ๊ทธ๋ฃน์˜ ํ‰๊ท ์ด ๊ฐ™์€๊ฐ€/๋‹ค๋ฅธ๊ฐ€?โ€

โš ๏ธ ์ฃผ์˜: ๋‘ ๊ทธ๋ฃน์€ ์„œ๋กœ ๋…๋ฆฝ์ ์ด์–ด์•ผ ํ•จ (๊ฐ™์€ ์‚ฌ๋žŒ์ด ๋‘ ๊ทธ๋ฃน์— ์†ํ•˜๋ฉด ์•ˆ ๋จ)

# Titanic: ์„ฑ๋ณ„์— ๋”ฐ๋ฅธ ์šด์ž„ ๋น„๊ต # ์ƒํ™ฉ: ํƒ€์ดํƒ€๋‹‰ํ˜ธ์—์„œ ๋‚จ์„ฑ๊ณผ ์—ฌ์„ฑ์ด ์ง€๋ถˆํ•œ ์šด์ž„์— ์ฐจ์ด๊ฐ€ ์žˆ์—ˆ๋Š”์ง€ ๋ถ„์„ male_fare = titanic[titanic['sex'] == 'male']['fare'].dropna() female_fare = titanic[titanic['sex'] == 'female']['fare'].dropna() # ๋“ฑ๋ถ„์‚ฐ ๊ฐ€์ • ๊ฒ€์ • _, levene_p = levene(male_fare, female_fare) equal_var = levene_p >= 0.05 # t-๊ฒ€์ • (Welch's t-test if unequal variance) stat, p_value = ttest_ind(male_fare, female_fare, equal_var=equal_var) print("=== ๋…๋ฆฝํ‘œ๋ณธ t-๊ฒ€์ • ===") print(f"Hโ‚€: ๋‚จ์„ฑ ํ‰๊ท  ์šด์ž„ = ์—ฌ์„ฑ ํ‰๊ท  ์šด์ž„") print(f"Hโ‚: ๋‚จ์„ฑ ํ‰๊ท  ์šด์ž„ โ‰  ์—ฌ์„ฑ ํ‰๊ท  ์šด์ž„") print(f"\n๋‚จ์„ฑ ํ‰๊ท  ์šด์ž„: ${male_fare.mean():.2f} (n={len(male_fare)})") print(f"์—ฌ์„ฑ ํ‰๊ท  ์šด์ž„: ${female_fare.mean():.2f} (n={len(female_fare)})") print(f"์ฐจ์ด: ${female_fare.mean() - male_fare.mean():.2f}") print(f"\n๋“ฑ๋ถ„์‚ฐ ๊ฐ€์ •: {'์ถฉ์กฑ (Student t-test)' if equal_var else '๋ถˆ์ถฉ์กฑ (Welch t-test ์‚ฌ์šฉ)'}") print(f"t-ํ†ต๊ณ„๋Ÿ‰: {stat:.4f}") print(f"p-value: {p_value:.4f}") print(f"\n๊ฒฐ๋ก : {'์„ฑ๋ณ„์— ๋”ฐ๋ฅธ ์šด์ž„ ์ฐจ์ด๊ฐ€ ์œ ์˜ํ•จ' if p_value < 0.05 else '์„ฑ๋ณ„์— ๋”ฐ๋ฅธ ์šด์ž„ ์ฐจ์ด ์—†์Œ'}")
์‹คํ–‰ ๊ฒฐ๊ณผ
=== ๋…๋ฆฝํ‘œ๋ณธ t-๊ฒ€์ • ===
Hโ‚€: ๋‚จ์„ฑ ํ‰๊ท  ์šด์ž„ = ์—ฌ์„ฑ ํ‰๊ท  ์šด์ž„
Hโ‚: ๋‚จ์„ฑ ํ‰๊ท  ์šด์ž„ โ‰  ์—ฌ์„ฑ ํ‰๊ท  ์šด์ž„

๋‚จ์„ฑ ํ‰๊ท  ์šด์ž„: $25.52 (n=577)
์—ฌ์„ฑ ํ‰๊ท  ์šด์ž„: $44.48 (n=314)
์ฐจ์ด: $18.95

๋“ฑ๋ถ„์‚ฐ ๊ฐ€์ •: ๋ถˆ์ถฉ์กฑ (Welch t-test ์‚ฌ์šฉ)
t-ํ†ต๊ณ„๋Ÿ‰: -4.7994
p-value: 0.0000

๊ฒฐ๋ก : ์„ฑ๋ณ„์— ๋”ฐ๋ฅธ ์šด์ž„ ์ฐจ์ด๊ฐ€ ์œ ์˜ํ•จ

๋Œ€์‘ํ‘œ๋ณธ t-๊ฒ€์ • (Paired Samples T-Test)

๐Ÿ“Œ ์‚ฌ์šฉ ์ƒํ™ฉ ์˜ˆ์‹œ

  • ๋‹ค์ด์–ดํŠธ ํšจ๊ณผ: ๊ฐ™์€ ์‚ฌ๋žŒ๋“ค์˜ ๋‹ค์ด์–ดํŠธ ์ „ํ›„ ์ฒด์ค‘ ๋น„๊ต
  • ๊ต์œก ํšจ๊ณผ: ๊ฐ™์€ ํ•™์ƒ๋“ค์˜ ์ˆ˜์—… ์ „ํ›„ ์‹œํ—˜ ์ ์ˆ˜ ๋น„๊ต
  • ์•ฝ๋ฌผ ํšจ๊ณผ: ๊ฐ™์€ ํ™˜์ž์˜ ํˆฌ์•ฝ ์ „ํ›„ ํ˜ˆ์•• ๋น„๊ต
  • UX ๊ฐœ์„ : ๊ฐ™์€ ์‚ฌ์šฉ์ž๊ฐ€ ๊ตฌ๋ฒ„์ „/์‹ ๋ฒ„์ „ ์•ฑ์„ ์‚ฌ์šฉํ–ˆ์„ ๋•Œ ์ž‘์—… ์™„๋ฃŒ ์‹œ๊ฐ„ ๋น„๊ต
  • ๋งˆ์ผ€ํŒ…: ๊ฐ™์€ ๋งค์žฅ์˜ ํ”„๋กœ๋ชจ์…˜ ์ „ํ›„ ๋งค์ถœ ๋น„๊ต

๐Ÿ’ก ํ•ต์‹ฌ ์งˆ๋ฌธ: โ€œ๊ฐ™์€ ๋Œ€์ƒ์˜ ์ฒ˜์น˜ ์ „ํ›„ ๊ฐ’์ด ๋‹ฌ๋ผ์กŒ๋Š”๊ฐ€?โ€

โš ๏ธ ๋…๋ฆฝํ‘œ๋ณธ๊ณผ์˜ ์ฐจ์ด: ๋Œ€์‘ํ‘œ๋ณธ์€ ๊ฐ™์€ ๋Œ€์ƒ์„ ๋‘ ๋ฒˆ ์ธก์ •ํ•˜๋ฏ€๋กœ ๊ฐœ์ธ์ฐจ๋ฅผ ํ†ต์ œํ•  ์ˆ˜ ์žˆ์–ด ๋” ๋ฏผ๊ฐํ•˜๊ฒŒ ๋ณ€ํ™”๋ฅผ ํƒ์ง€

# ์‹œ๋ฎฌ๋ ˆ์ด์…˜: A/B ํ…Œ์ŠคํŠธ ์ „ํ™˜์œจ (๊ฐ™์€ ์‚ฌ์šฉ์ž๊ฐ€ ๋‘ ๊ฐ€์ง€ UI๋ฅผ ๊ฒฝํ—˜) # ์ƒํ™ฉ: 100๋ช…์˜ ์‚ฌ์šฉ์ž์—๊ฒŒ ๊ตฌ๋ฒ„์ „ UI์™€ ์‹ ๋ฒ„์ „ UI๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ ๋ณด์—ฌ์ฃผ๊ณ  ํด๋ฆญ๋ฅ  ์ธก์ • np.random.seed(42) n_users = 100 # Before: ๊ธฐ์กด UI ํด๋ฆญ๋ฅ  before = np.random.beta(2, 8, n_users) # ํ‰๊ท  ์•ฝ 20% # After: ์ƒˆ UI ํด๋ฆญ๋ฅ  (์•ฝ๊ฐ„์˜ ๊ฐœ์„ ) after = before + np.random.normal(0.05, 0.03, n_users) after = np.clip(after, 0, 1) stat, p_value = ttest_rel(before, after) print("=== ๋Œ€์‘ํ‘œ๋ณธ t-๊ฒ€์ • ===") print(f"Hโ‚€: ์ „ํ™˜์œจ ๋ณ€ํ™” ์—†์Œ (์ƒˆ UI ํšจ๊ณผ ์—†์Œ)") print(f"Hโ‚: ์ „ํ™˜์œจ ๋ณ€ํ™” ์žˆ์Œ (์ƒˆ UI ํšจ๊ณผ ์žˆ์Œ)") print(f"\nBefore (๊ธฐ์กด UI) ํ‰๊ท : {before.mean():.4f} ({before.mean()*100:.1f}%)") print(f"After (์ƒˆ UI) ํ‰๊ท : {after.mean():.4f} ({after.mean()*100:.1f}%)") print(f"ํ‰๊ท  ์ฐจ์ด: {(after - before).mean():.4f} (+{(after - before).mean()*100:.1f}%p)") print(f"\nt-ํ†ต๊ณ„๋Ÿ‰: {stat:.4f}") print(f"p-value: {p_value:.4f}") print(f"\n๊ฒฐ๋ก : {'์ƒˆ UI๊ฐ€ ์œ ์˜๋ฏธํ•˜๊ฒŒ ๊ฐœ์„ ๋จ' if p_value < 0.05 else '์œ ์˜๋ฏธํ•œ ๋ณ€ํ™” ์—†์Œ'}")
์‹คํ–‰ ๊ฒฐ๊ณผ
=== ๋Œ€์‘ํ‘œ๋ณธ t-๊ฒ€์ • ===
Hโ‚€: ์ „ํ™˜์œจ ๋ณ€ํ™” ์—†์Œ (์ƒˆ UI ํšจ๊ณผ ์—†์Œ)
Hโ‚: ์ „ํ™˜์œจ ๋ณ€ํ™” ์žˆ์Œ (์ƒˆ UI ํšจ๊ณผ ์žˆ์Œ)

Before (๊ธฐ์กด UI) ํ‰๊ท : 0.2037 (20.4%)
After (์ƒˆ UI) ํ‰๊ท : 0.2503 (25.0%)
ํ‰๊ท  ์ฐจ์ด: 0.0466 (+4.7%p)

t-ํ†ต๊ณ„๋Ÿ‰: -14.7221
p-value: 0.0000

๊ฒฐ๋ก : ์ƒˆ UI๊ฐ€ ์œ ์˜๋ฏธํ•˜๊ฒŒ ๊ฐœ์„ ๋จ

5. ๋น„๋ชจ์ˆ˜ ๊ฒ€์ • (Non-parametric Tests)

๐ŸŽฏ ์–ธ์ œ ์‚ฌ์šฉํ•˜๋‚˜์š”?

  • ๋ฐ์ดํ„ฐ๊ฐ€ ์ •๊ทœ๋ถ„ํฌ๋ฅผ ๋”ฐ๋ฅด์ง€ ์•Š์„ ๋•Œ
  • ํ‘œ๋ณธ ํฌ๊ธฐ๊ฐ€ ์ž‘์„ ๋•Œ (n < 30)
  • ์ˆœ์œ„ ๋ฐ์ดํ„ฐ๋‚˜ ์„œ์—ด ์ฒ™๋„ ๋ฐ์ดํ„ฐ์ผ ๋•Œ
  • ์ด์ƒ์น˜(outlier)๊ฐ€ ๋งŽ์„ ๋•Œ (๋น„๋ชจ์ˆ˜ ๊ฒ€์ •์€ ์ด์ƒ์น˜์— ๋œ ๋ฏผ๊ฐ)

Mann-Whitney U Test

๐Ÿ“Œ ์‚ฌ์šฉ ์ƒํ™ฉ ์˜ˆ์‹œ

  • ์ „์ž์ƒ๊ฑฐ๋ž˜: ํ”„๋ฆฌ๋ฏธ์—„ ํšŒ์›๊ณผ ์ผ๋ฐ˜ ํšŒ์›์˜ ์ฃผ๋ฌธ ๊ธˆ์•ก ๋ถ„ํฌ ๋น„๊ต (๊ธˆ์•ก ๋ฐ์ดํ„ฐ๋Š” ๋ณดํ†ต ์˜ค๋ฅธ์ชฝ ๊ผฌ๋ฆฌ๊ฐ€ ๊ธด ๋น„์ •๊ทœ ๋ถ„ํฌ)
  • ๊ฒŒ์ž„: ๊ณผ๊ธˆ ์œ ์ €์™€ ๋ฌด๊ณผ๊ธˆ ์œ ์ €์˜ ํ”Œ๋ ˆ์ด ์‹œ๊ฐ„ ๋น„๊ต
  • ์˜ํ•™: ๋‘ ์น˜๋ฃŒ๋ฒ•์˜ ํ†ต์ฆ ์ฒ™๋„(1-10) ๋น„๊ต
  • ๋งŒ์กฑ๋„: ๋‘ ์ œํ’ˆ์˜ ๊ณ ๊ฐ ํ‰์  ๋ถ„ํฌ ๋น„๊ต

๐Ÿ’ก ํ•ต์‹ฌ ์งˆ๋ฌธ: โ€œ๋‘ ๋…๋ฆฝ ๊ทธ๋ฃน์˜ **๋ถ„ํฌ(์ˆœ์œ„)**๊ฐ€ ๋‹ค๋ฅธ๊ฐ€?โ€

โš ๏ธ ๋…๋ฆฝํ‘œ๋ณธ t-๊ฒ€์ •์˜ ๋น„๋ชจ์ˆ˜ ๋Œ€์•ˆ. ํ‰๊ท ์ด ์•„๋‹Œ ์ค‘์•™๊ฐ’/์ˆœ์œ„๋ฅผ ๋น„๊ตํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋จ.

# Diamonds: ์ปคํŒ… ํ’ˆ์งˆ์— ๋”ฐ๋ฅธ ๊ฐ€๊ฒฉ ๋น„๊ต (Ideal vs Good) # ์ƒํ™ฉ: ๋‹ค์ด์•„๋ชฌ๋“œ ์ปคํŒ… ํ’ˆ์งˆ์ด Ideal์ธ ๊ฒƒ๊ณผ Good์ธ ๊ฒƒ์˜ ๊ฐ€๊ฒฉ ๋ถ„ํฌ ๋น„๊ต # ๊ฐ€๊ฒฉ ๋ฐ์ดํ„ฐ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์ •๊ทœ๋ถ„ํฌ๋ฅผ ๋”ฐ๋ฅด์ง€ ์•Š์œผ๋ฏ€๋กœ ๋น„๋ชจ์ˆ˜ ๊ฒ€์ • ์‚ฌ์šฉ ideal_price = diamonds[diamonds['cut'] == 'Ideal']['price'] good_price = diamonds[diamonds['cut'] == 'Good']['price'] stat, p_value = mannwhitneyu(ideal_price, good_price, alternative='two-sided') print("=== Mann-Whitney U ๊ฒ€์ • ===") print(f"Hโ‚€: Ideal ์ปคํŒ…๊ณผ Good ์ปคํŒ…์˜ ๊ฐ€๊ฒฉ ๋ถ„ํฌ๊ฐ€ ๊ฐ™๋‹ค") print(f"Hโ‚: ๊ฐ€๊ฒฉ ๋ถ„ํฌ๊ฐ€ ๋‹ค๋ฅด๋‹ค") print(f"\nIdeal ์ค‘์•™๊ฐ’: ${ideal_price.median():,.2f} (n={len(ideal_price)})") print(f"Good ์ค‘์•™๊ฐ’: ${good_price.median():,.2f} (n={len(good_price)})") print(f"\nU-ํ†ต๊ณ„๋Ÿ‰: {stat:,.2f}") print(f"p-value: {p_value:.4f}") print(f"\n๊ฒฐ๋ก : {'๊ฐ€๊ฒฉ ๋ถ„ํฌ๊ฐ€ ์œ ์˜ํ•˜๊ฒŒ ๋‹ค๋ฆ„' if p_value < 0.05 else '๊ฐ€๊ฒฉ ๋ถ„ํฌ ์ฐจ์ด ์—†์Œ'}")
์‹คํ–‰ ๊ฒฐ๊ณผ
=== Mann-Whitney U ๊ฒ€์ • ===
Hโ‚€: Ideal ์ปคํŒ…๊ณผ Good ์ปคํŒ…์˜ ๊ฐ€๊ฒฉ ๋ถ„ํฌ๊ฐ€ ๊ฐ™๋‹ค
Hโ‚: ๊ฐ€๊ฒฉ ๋ถ„ํฌ๊ฐ€ ๋‹ค๋ฅด๋‹ค

Ideal ์ค‘์•™๊ฐ’: $1,810.00 (n=393)
Good ์ค‘์•™๊ฐ’: $3,086.50 (n=96)

U-ํ†ต๊ณ„๋Ÿ‰: 14,985.00
p-value: 0.0031

๊ฒฐ๋ก : ๊ฐ€๊ฒฉ ๋ถ„ํฌ๊ฐ€ ์œ ์˜ํ•˜๊ฒŒ ๋‹ค๋ฆ„

Wilcoxon Signed-Rank Test

๐Ÿ“Œ ์‚ฌ์šฉ ์ƒํ™ฉ ์˜ˆ์‹œ

  • ์ฒด์ค‘ ๊ฐ๋Ÿ‰: ๋‹ค์ด์–ดํŠธ ํ”„๋กœ๊ทธ๋žจ ์ „ํ›„ ์ฒด์ค‘ ๋น„๊ต (์ฒด์ค‘ ๋ณ€ํ™”๊ฐ€ ์ •๊ทœ๋ถ„ํฌ๊ฐ€ ์•„๋‹ ๋•Œ)
  • ์„ค๋ฌธ์กฐ์‚ฌ: ๊ฐ™์€ ์‘๋‹ต์ž์˜ ์ •์ฑ… ๋ณ€๊ฒฝ ์ „ํ›„ ๋งŒ์กฑ๋„(1-5์ ) ๋น„๊ต
  • ๊ต์œก: ๊ฐ™์€ ํ•™์ƒ์˜ ํŠน๊ฐ• ์ „ํ›„ ์ž์‹ ๊ฐ ์ ์ˆ˜ ๋น„๊ต
  • ์•ฑ ํ‰์ : ์—…๋ฐ์ดํŠธ ์ „ํ›„ ๊ฐ™์€ ์‚ฌ์šฉ์ž์˜ ํ‰์  ๋ณ€ํ™”

๐Ÿ’ก ํ•ต์‹ฌ ์งˆ๋ฌธ: โ€œ๊ฐ™์€ ๋Œ€์ƒ์˜ ์ „ํ›„ ๊ฐ’ ๋ถ„ํฌ๊ฐ€ ๋‹ฌ๋ผ์กŒ๋Š”๊ฐ€?โ€

โš ๏ธ ๋Œ€์‘ํ‘œ๋ณธ t-๊ฒ€์ •์˜ ๋น„๋ชจ์ˆ˜ ๋Œ€์•ˆ. ์ฐจ์ด๊ฐ’์˜ ๋ถ€ํ˜ธ์™€ ์ˆœ์œ„๋ฅผ ์‚ฌ์šฉ.

# Tips: ์ ์‹ฌ vs ์ €๋… ํŒ๋ฅ  ๋น„๊ต (๊ฐ™์€ ์›จ์ดํ„ฐ) # ์ƒํ™ฉ: 50๋ช…์˜ ์›จ์ดํ„ฐ๊ฐ€ ์ ์‹ฌ๊ณผ ์ €๋…์— ๋ฐ›๋Š” ํŒ ๋น„์œจ์ด ๋‹ค๋ฅธ์ง€ ๊ฒ€์ • np.random.seed(42) n_waiters = 50 lunch_tip_rate = np.random.uniform(0.12, 0.22, n_waiters) dinner_tip_rate = lunch_tip_rate + np.random.normal(0.02, 0.03, n_waiters) stat, p_value = wilcoxon(lunch_tip_rate, dinner_tip_rate) print("=== Wilcoxon Signed-Rank ๊ฒ€์ • ===") print(f"Hโ‚€: ์ ์‹ฌ๊ณผ ์ €๋… ํŒ๋ฅ  ์ฐจ์ด ์—†์Œ") print(f"Hโ‚: ์ ์‹ฌ๊ณผ ์ €๋… ํŒ๋ฅ  ์ฐจ์ด ์žˆ์Œ") print(f"\n์ ์‹ฌ ํŒ๋ฅ  ์ค‘์•™๊ฐ’: {np.median(lunch_tip_rate)*100:.1f}%") print(f"์ €๋… ํŒ๋ฅ  ์ค‘์•™๊ฐ’: {np.median(dinner_tip_rate)*100:.1f}%") print(f"\nW-ํ†ต๊ณ„๋Ÿ‰: {stat:.2f}") print(f"p-value: {p_value:.4f}") print(f"\n๊ฒฐ๋ก : {'์ €๋… ํŒ๋ฅ ์ด ์œ ์˜ํ•˜๊ฒŒ ๋†’์Œ' if p_value < 0.05 else '์ฐจ์ด ์—†์Œ'}")
์‹คํ–‰ ๊ฒฐ๊ณผ
=== Wilcoxon Signed-Rank ๊ฒ€์ • ===
Hโ‚€: ์ ์‹ฌ๊ณผ ์ €๋… ํŒ๋ฅ  ์ฐจ์ด ์—†์Œ
Hโ‚: ์ ์‹ฌ๊ณผ ์ €๋… ํŒ๋ฅ  ์ฐจ์ด ์žˆ์Œ

์ ์‹ฌ ํŒ๋ฅ  ์ค‘์•™๊ฐ’: 16.9%
์ €๋… ํŒ๋ฅ  ์ค‘์•™๊ฐ’: 19.1%

W-ํ†ต๊ณ„๋Ÿ‰: 304.00
p-value: 0.0004

๊ฒฐ๋ก : ์ €๋… ํŒ๋ฅ ์ด ์œ ์˜ํ•˜๊ฒŒ ๋†’์Œ

Kruskal-Wallis H Test

๐Ÿ“Œ ์‚ฌ์šฉ ์ƒํ™ฉ ์˜ˆ์‹œ

  • ๋งˆ์ผ€ํŒ…: 3๊ฐ€์ง€ ๊ด‘๊ณ  ์œ ํ˜•(TV, ์˜จ๋ผ์ธ, SNS)๋ณ„ ๋ธŒ๋žœ๋“œ ์ธ์ง€๋„ ์ ์ˆ˜ ๋น„๊ต
  • ์ œํ’ˆ: ์—ฌ๋Ÿฌ ๋ธŒ๋žœ๋“œ ์Šค๋งˆํŠธํฐ์˜ ๊ณ ๊ฐ ๋งŒ์กฑ๋„ ๋น„๊ต
  • ๊ต์œก: 3๊ฐœ ํ•™๊ต์˜ ํ•™์ƒ ์„ฑ์  ๋ถ„ํฌ ๋น„๊ต
  • ์˜ํ•™: ์—ฌ๋Ÿฌ ์น˜๋ฃŒ๋ฒ•์˜ ํšŒ๋ณต ๊ธฐ๊ฐ„ ๋น„๊ต (๋น„์ •๊ทœ ๋ฐ์ดํ„ฐ)

๐Ÿ’ก ํ•ต์‹ฌ ์งˆ๋ฌธ: โ€œ3๊ฐœ ์ด์ƒ ๊ทธ๋ฃน์˜ ๋ถ„ํฌ๊ฐ€ ๋ชจ๋‘ ๊ฐ™์€๊ฐ€, ์•„๋‹ˆ๋ฉด ์ ์–ด๋„ ํ•˜๋‚˜๊ฐ€ ๋‹ค๋ฅธ๊ฐ€?โ€

โš ๏ธ One-Way ANOVA์˜ ๋น„๋ชจ์ˆ˜ ๋Œ€์•ˆ. ์–ด๋–ค ๊ทธ๋ฃน์ด ๋‹ค๋ฅธ์ง€๋Š” ์‚ฌํ›„๊ฒ€์ • ํ•„์š”.

# Iris: ํ’ˆ์ข…๋ณ„ ๊ฝƒ์žŽ ๋„ˆ๋น„ ๋น„๊ต # ์ƒํ™ฉ: ์„ธ ๊ฐ€์ง€ ๋ถ“๊ฝƒ ํ’ˆ์ข…(setosa, versicolor, virginica)์˜ ๊ฝƒ์žŽ ๋„ˆ๋น„ ๋ถ„ํฌ๊ฐ€ ๋‹ค๋ฅธ์ง€ ๊ฒ€์ • setosa_pw = iris[iris['species'] == 'setosa']['petal_width'] versicolor_pw = iris[iris['species'] == 'versicolor']['petal_width'] virginica_pw = iris[iris['species'] == 'virginica']['petal_width'] stat, p_value = kruskal(setosa_pw, versicolor_pw, virginica_pw) print("=== Kruskal-Wallis H ๊ฒ€์ • ===") print(f"Hโ‚€: ๋ชจ๋“  ํ’ˆ์ข…์˜ ๊ฝƒ์žŽ ๋„ˆ๋น„ ๋ถ„ํฌ๊ฐ€ ๊ฐ™๋‹ค") print(f"Hโ‚: ์ ์–ด๋„ ํ•˜๋‚˜์˜ ํ’ˆ์ข…์ด ๋‹ค๋ฅด๋‹ค") print(f"\nSetosa ์ค‘์•™๊ฐ’: {setosa_pw.median():.2f}cm") print(f"Versicolor ์ค‘์•™๊ฐ’: {versicolor_pw.median():.2f}cm") print(f"Virginica ์ค‘์•™๊ฐ’: {virginica_pw.median():.2f}cm") print(f"\nH-ํ†ต๊ณ„๋Ÿ‰: {stat:.4f}") print(f"p-value: {p_value:.6f}") print(f"\n๊ฒฐ๋ก : {'ํ’ˆ์ข… ๊ฐ„ ์œ ์˜ํ•œ ์ฐจ์ด ์žˆ์Œ' if p_value < 0.05 else '์ฐจ์ด ์—†์Œ'}")
์‹คํ–‰ ๊ฒฐ๊ณผ
=== Kruskal-Wallis H ๊ฒ€์ • ===
Hโ‚€: ๋ชจ๋“  ํ’ˆ์ข…์˜ ๊ฝƒ์žŽ ๋„ˆ๋น„ ๋ถ„ํฌ๊ฐ€ ๊ฐ™๋‹ค
Hโ‚: ์ ์–ด๋„ ํ•˜๋‚˜์˜ ํ’ˆ์ข…์ด ๋‹ค๋ฅด๋‹ค

Setosa ์ค‘์•™๊ฐ’: 0.20cm
Versicolor ์ค‘์•™๊ฐ’: 1.30cm
Virginica ์ค‘์•™๊ฐ’: 2.00cm

H-ํ†ต๊ณ„๋Ÿ‰: 130.0111
p-value: 0.000000

๊ฒฐ๋ก : ํ’ˆ์ข… ๊ฐ„ ์œ ์˜ํ•œ ์ฐจ์ด ์žˆ์Œ

6. ๋ถ„์‚ฐ๋ถ„์„ (ANOVA)

์ผ์›๋ถ„์‚ฐ๋ถ„์„ (One-Way ANOVA)

๐Ÿ“Œ ์‚ฌ์šฉ ์ƒํ™ฉ ์˜ˆ์‹œ

  • ๋งˆ์ผ€ํŒ…: 4๊ฐ€์ง€ ํ”„๋กœ๋ชจ์…˜ ์œ ํ˜•(ํ• ์ธ, ์ ๋ฆฝ, ์‚ฌ์€ํ’ˆ, ๋ฌด๋ฃŒ๋ฐฐ์†ก)์˜ ํ‰๊ท  ๊ตฌ๋งค์•ก ๋น„๊ต
  • ์ œ์กฐ: 3๊ฐœ ๊ณต์žฅ์—์„œ ์ƒ์‚ฐ๋œ ์ œํ’ˆ์˜ ํ‰๊ท  ํ’ˆ์งˆ ์ ์ˆ˜ ๋น„๊ต
  • HR: ๋ถ€์„œ๋ณ„(๊ฐœ๋ฐœ, ๋งˆ์ผ€ํŒ…, ์˜์—…, ์ง€์›) ์ง์› ๋งŒ์กฑ๋„ ๋น„๊ต
  • ๊ต์œก: ์—ฌ๋Ÿฌ ๊ต์ˆ˜๋ฒ•์˜ ํ•™์Šต ํšจ๊ณผ ๋น„๊ต

๐Ÿ’ก ํ•ต์‹ฌ ์งˆ๋ฌธ: โ€œ3๊ฐœ ์ด์ƒ ๊ทธ๋ฃน์˜ ํ‰๊ท ์ด ๋ชจ๋‘ ๊ฐ™์€๊ฐ€?โ€

โš ๏ธ ์ „์ œ์กฐ๊ฑด: ์ •๊ทœ์„ฑ, ๋“ฑ๋ถ„์‚ฐ์„ฑ. ์œ„๋ฐฐ ์‹œ Kruskal-Wallis ์‚ฌ์šฉ.

# Tips: ์š”์ผ๋ณ„ ์ด ๊ฒฐ์ œ ๊ธˆ์•ก ๋น„๊ต # ์ƒํ™ฉ: ์š”์ผ์— ๋”ฐ๋ผ ๊ณ ๊ฐ๋“ค์˜ ํ‰๊ท  ๊ฒฐ์ œ ๊ธˆ์•ก์ด ๋‹ค๋ฅธ์ง€ ๋ถ„์„ thur = tips[tips['day'] == 'Thur']['total_bill'] fri = tips[tips['day'] == 'Fri']['total_bill'] sat = tips[tips['day'] == 'Sat']['total_bill'] sun = tips[tips['day'] == 'Sun']['total_bill'] stat, p_value = f_oneway(thur, fri, sat, sun) print("=== One-Way ANOVA ===") print(f"Hโ‚€: ๋ชจ๋“  ์š”์ผ์˜ ํ‰๊ท  ๊ฒฐ์ œ ๊ธˆ์•ก์ด ๊ฐ™๋‹ค") print(f"Hโ‚: ์ ์–ด๋„ ํ•˜๋‚˜์˜ ์š”์ผ์ด ๋‹ค๋ฅด๋‹ค") print(f"\n์š”์ผ๋ณ„ ํ‰๊ท  ๊ฒฐ์ œ ๊ธˆ์•ก:") print(f" ๋ชฉ์š”์ผ: ${thur.mean():.2f} (n={len(thur)})") print(f" ๊ธˆ์š”์ผ: ${fri.mean():.2f} (n={len(fri)})") print(f" ํ† ์š”์ผ: ${sat.mean():.2f} (n={len(sat)})") print(f" ์ผ์š”์ผ: ${sun.mean():.2f} (n={len(sun)})") print(f"\nF-ํ†ต๊ณ„๋Ÿ‰: {stat:.4f}") print(f"p-value: {p_value:.4f}") print(f"\n๊ฒฐ๋ก : {'์š”์ผ๋ณ„ ์œ ์˜ํ•œ ์ฐจ์ด ์žˆ์Œ โ†’ ์‚ฌํ›„๊ฒ€์ • ํ•„์š”' if p_value < 0.05 else '์š”์ผ๋ณ„ ์ฐจ์ด ์—†์Œ'}")
์‹คํ–‰ ๊ฒฐ๊ณผ
=== One-Way ANOVA ===
Hโ‚€: ๋ชจ๋“  ์š”์ผ์˜ ํ‰๊ท  ๊ฒฐ์ œ ๊ธˆ์•ก์ด ๊ฐ™๋‹ค
Hโ‚: ์ ์–ด๋„ ํ•˜๋‚˜์˜ ์š”์ผ์ด ๋‹ค๋ฅด๋‹ค

์š”์ผ๋ณ„ ํ‰๊ท  ๊ฒฐ์ œ ๊ธˆ์•ก:
๋ชฉ์š”์ผ: $17.68 (n=62)
๊ธˆ์š”์ผ: $17.15 (n=19)
ํ† ์š”์ผ: $20.44 (n=87)
์ผ์š”์ผ: $21.41 (n=76)

F-ํ†ต๊ณ„๋Ÿ‰: 2.7675
p-value: 0.0424

๊ฒฐ๋ก : ์š”์ผ๋ณ„ ์œ ์˜ํ•œ ์ฐจ์ด ์žˆ์Œ โ†’ ์‚ฌํ›„๊ฒ€์ • ํ•„์š”

์ด์›๋ถ„์‚ฐ๋ถ„์„ (Two-Way ANOVA)

๐Ÿ“Œ ์‚ฌ์šฉ ์ƒํ™ฉ ์˜ˆ์‹œ

  • ๋งˆ์ผ€ํŒ…: **๊ด‘๊ณ  ์ฑ„๋„(TV/์˜จ๋ผ์ธ)**๊ณผ **ํƒ€๊ฒŸ ์—ฐ๋ น๋Œ€(20๋Œ€/30๋Œ€/40๋Œ€)**๊ฐ€ ๊ตฌ๋งค ์˜ํ–ฅ์— ๋ฏธ์น˜๋Š” ์˜ํ–ฅ ๋ถ„์„
  • ์ œ์กฐ: ๊ธฐ๊ณ„ ์ข…๋ฅ˜์™€ ์ž‘์—…์ž ์ˆ™๋ จ๋„๊ฐ€ ์ƒ์‚ฐ๋Ÿ‰์— ๋ฏธ์น˜๋Š” ์˜ํ–ฅ
  • ๊ต์œก: ๊ต์ˆ˜๋ฒ•๊ณผ ํ•™๊ธ‰ ๊ทœ๋ชจ๊ฐ€ ํ•™์Šต ์„ฑ๊ณผ์— ๋ฏธ์น˜๋Š” ์˜ํ–ฅ
  • ์˜ํ•™: ์•ฝ๋ฌผ ์ข…๋ฅ˜์™€ ํˆฌ์•ฝ ์šฉ๋Ÿ‰์ด ์น˜๋ฃŒ ํšจ๊ณผ์— ๋ฏธ์น˜๋Š” ์˜ํ–ฅ

๐Ÿ’ก ํ•ต์‹ฌ ์งˆ๋ฌธ:

  1. ์š”์ธ A์˜ ์ฃผํšจ๊ณผ๊ฐ€ ์žˆ๋Š”๊ฐ€?
  2. ์š”์ธ B์˜ ์ฃผํšจ๊ณผ๊ฐ€ ์žˆ๋Š”๊ฐ€?
  3. A์™€ B์˜ ์ƒํ˜ธ์ž‘์šฉ ํšจ๊ณผ๊ฐ€ ์žˆ๋Š”๊ฐ€? (์˜ˆ: ํŠน์ • ์กฐํ•ฉ์—์„œ๋งŒ ํšจ๊ณผ๊ฐ€ ์žˆ๋Š”์ง€)
import statsmodels.api as sm from statsmodels.formula.api import ols # Tips: ์„ฑ๋ณ„๊ณผ ํก์—ฐ ์—ฌ๋ถ€๊ฐ€ ํŒ์— ๋ฏธ์น˜๋Š” ์˜ํ–ฅ # ์ƒํ™ฉ: ํŒ ๊ธˆ์•ก์ด ์„ฑ๋ณ„๊ณผ ํก์—ฐ ์—ฌ๋ถ€์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง€๋Š”์ง€, ๊ทธ๋ฆฌ๊ณ  ์ด ๋‘˜์˜ ์กฐํ•ฉ ํšจ๊ณผ๊ฐ€ ์žˆ๋Š”์ง€ ๋ถ„์„ model = ols('tip ~ C(sex) + C(smoker) + C(sex):C(smoker)', data=tips).fit() anova_table = sm.stats.anova_lm(model, typ=2) print("=== Two-Way ANOVA ===") print(f"์ข…์†๋ณ€์ˆ˜: ํŒ ๊ธˆ์•ก") print(f"์š”์ธ 1: ์„ฑ๋ณ„ (sex)") print(f"์š”์ธ 2: ํก์—ฐ ์—ฌ๋ถ€ (smoker)") print(f"\n{anova_table.round(4)}") print("\nํ•ด์„:") for idx, row in anova_table.iterrows(): if idx != 'Residual': sig = "์œ ์˜ํ•จ ***" if row['PR(>F)'] < 0.001 else \ "์œ ์˜ํ•จ **" if row['PR(>F)'] < 0.01 else \ "์œ ์˜ํ•จ *" if row['PR(>F)'] < 0.05 else "์œ ์˜ํ•˜์ง€ ์•Š์Œ" print(f" {idx}: p = {row['PR(>F)']:.4f} โ†’ {sig}")
์‹คํ–‰ ๊ฒฐ๊ณผ
=== Two-Way ANOVA ===
์ข…์†๋ณ€์ˆ˜: ํŒ ๊ธˆ์•ก
์š”์ธ 1: ์„ฑ๋ณ„ (sex)
์š”์ธ 2: ํก์—ฐ ์—ฌ๋ถ€ (smoker)

                     sum_sq     df         F    PR(>F)
C(sex)                  1.0554    1.0    0.5596    0.4551
C(smoker)               0.1477    1.0    0.0783    0.7799
C(sex):C(smoker)        0.2077    1.0    0.1101    0.7404
Residual              452.5604  240.0       NaN       NaN

ํ•ด์„:
C(sex): p = 0.4551 โ†’ ์œ ์˜ํ•˜์ง€ ์•Š์Œ
C(smoker): p = 0.7799 โ†’ ์œ ์˜ํ•˜์ง€ ์•Š์Œ
C(sex):C(smoker): p = 0.7404 โ†’ ์œ ์˜ํ•˜์ง€ ์•Š์Œ

7. ์นด์ด์ œ๊ณฑ ๊ฒ€์ • (Chi-Square Tests)

๋…๋ฆฝ์„ฑ ๊ฒ€์ • (Test of Independence)

๐Ÿ“Œ ์‚ฌ์šฉ ์ƒํ™ฉ ์˜ˆ์‹œ

  • ๋งˆ์ผ€ํŒ…: ์—ฐ๋ น๋Œ€(20๋Œ€/30๋Œ€/40๋Œ€)์™€ ์„ ํ˜ธ ๋ธŒ๋žœ๋“œ(A/B/C)๊ฐ€ ์—ฐ๊ด€๋˜์–ด ์žˆ๋Š”์ง€ ๋ถ„์„
  • ์˜ํ•™: ํก์—ฐ ์—ฌ๋ถ€์™€ ํ์•” ๋ฐœ์ƒ์ด ์—ฐ๊ด€๋˜์–ด ์žˆ๋Š”์ง€ ๊ฒ€์ •
  • ๊ต์œก: ์„ฑ๋ณ„๊ณผ ์ „๊ณต ์„ ํƒ์ด ์—ฐ๊ด€๋˜์–ด ์žˆ๋Š”์ง€ ๋ถ„์„
  • HR: ํ•™๋ ฅ๊ณผ ์ด์ง ์—ฌ๋ถ€๊ฐ€ ์—ฐ๊ด€๋˜์–ด ์žˆ๋Š”์ง€ ๋ถ„์„
  • ์„ ๊ฑฐ: ์ง€์—ญ๊ณผ ์ง€์ง€ ์ •๋‹น์ด ์—ฐ๊ด€๋˜์–ด ์žˆ๋Š”์ง€ ๋ถ„์„

๐Ÿ’ก ํ•ต์‹ฌ ์งˆ๋ฌธ: โ€œ๋‘ ๋ฒ”์ฃผํ˜• ๋ณ€์ˆ˜๊ฐ€ ์„œ๋กœ ๋…๋ฆฝ์ธ๊ฐ€, ์—ฐ๊ด€๋˜์–ด ์žˆ๋Š”๊ฐ€?โ€

# Titanic: ์„ฑ๋ณ„๊ณผ ์ƒ์กด ์—ฌ๋ถ€์˜ ๊ด€๊ณ„ # ์ƒํ™ฉ: ํƒ€์ดํƒ€๋‹‰ํ˜ธ ์นจ๋ชฐ ์‹œ ์„ฑ๋ณ„์— ๋”ฐ๋ผ ์ƒ์กด์œจ์ด ๋‹ฌ๋ž๋Š”์ง€ ๋ถ„์„ ("์—ฌ์„ฑ๊ณผ ์•„์ด ๋จผ์ €" ๊ทœ์น™) contingency = pd.crosstab(titanic['sex'], titanic['survived']) print("๊ต์ฐจํ‘œ:") print(contingency) print() chi2, p_value, dof, expected = chi2_contingency(contingency) print("=== ์นด์ด์ œ๊ณฑ ๋…๋ฆฝ์„ฑ ๊ฒ€์ • ===") print(f"Hโ‚€: ์„ฑ๋ณ„๊ณผ ์ƒ์กด ์—ฌ๋ถ€๋Š” ๋…๋ฆฝ์ ์ด๋‹ค (๊ด€๋ จ ์—†์Œ)") print(f"Hโ‚: ์„ฑ๋ณ„๊ณผ ์ƒ์กด ์—ฌ๋ถ€๋Š” ์—ฐ๊ด€์ด ์žˆ๋‹ค") print(f"\nฯ‡ยฒ ํ†ต๊ณ„๋Ÿ‰: {chi2:.4f}") print(f"์ž์œ ๋„: {dof}") print(f"p-value: {p_value:.6f}") print(f"\n๊ธฐ๋Œ€๋นˆ๋„ (๋…๋ฆฝ์ด๋ผ๋ฉด ์ด ์ •๋„๊ฐ€ ์˜ˆ์ƒ๋จ):") print(pd.DataFrame(expected, index=contingency.index, columns=contingency.columns).round(1)) print(f"\n๊ฒฐ๋ก : {'์„ฑ๋ณ„๊ณผ ์ƒ์กด์€ ๊ฐ•ํ•˜๊ฒŒ ์—ฐ๊ด€๋จ (์—ฌ์„ฑ ์ƒ์กด์œจ์ด ๋†’์Œ)' if p_value < 0.05 else '๋…๋ฆฝ์ '}")
์‹คํ–‰ ๊ฒฐ๊ณผ
๊ต์ฐจํ‘œ:
survived    0    1
sex
female     81  233
male      468  109

=== ์นด์ด์ œ๊ณฑ ๋…๋ฆฝ์„ฑ ๊ฒ€์ • ===
Hโ‚€: ์„ฑ๋ณ„๊ณผ ์ƒ์กด ์—ฌ๋ถ€๋Š” ๋…๋ฆฝ์ ์ด๋‹ค (๊ด€๋ จ ์—†์Œ)
Hโ‚: ์„ฑ๋ณ„๊ณผ ์ƒ์กด ์—ฌ๋ถ€๋Š” ์—ฐ๊ด€์ด ์žˆ๋‹ค

ฯ‡ยฒ ํ†ต๊ณ„๋Ÿ‰: 260.7170
์ž์œ ๋„: 1
p-value: 0.000000

๊ธฐ๋Œ€๋นˆ๋„ (๋…๋ฆฝ์ด๋ผ๋ฉด ์ด ์ •๋„๊ฐ€ ์˜ˆ์ƒ๋จ):
survived      0      1
sex
female    193.5  120.5
male      355.5  221.5

๊ฒฐ๋ก : ์„ฑ๋ณ„๊ณผ ์ƒ์กด์€ ๊ฐ•ํ•˜๊ฒŒ ์—ฐ๊ด€๋จ (์—ฌ์„ฑ ์ƒ์กด์œจ์ด ๋†’์Œ)

์ ํ•ฉ๋„ ๊ฒ€์ • (Goodness of Fit)

๐Ÿ“Œ ์‚ฌ์šฉ ์ƒํ™ฉ ์˜ˆ์‹œ

  • ํ’ˆ์งˆ๊ด€๋ฆฌ: ๋ถˆ๋Ÿ‰ํ’ˆ ๋ฐœ์ƒ์ด ๊ท ๋“ฑํ•˜๊ฒŒ(1/5์”ฉ) ๊ฐ ์š”์ผ์— ๋ถ„ํฌํ•˜๋Š”์ง€ ๊ฒ€์ •
  • ๋งˆ์ผ€ํŒ…: ๊ณ ๊ฐ ๋ถ„ํฌ๊ฐ€ **๊ธฐ๋Œ€ํ•œ ๋น„์œจ(40:35:25)**๊ณผ ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธ
  • ์œ ์ „ํ•™: ๊ด€์ธก๋œ ์œ ์ „ํ˜• ๋น„์œจ์ด **๋ฉ˜๋ธ์˜ ๋ฒ•์น™(9:3:3:1)**๊ณผ ๋งž๋Š”์ง€ ๊ฒ€์ •
  • ์„ค๋ฌธ: ์‘๋‹ต ๋ถ„ํฌ๊ฐ€ ๊ท ๋“ฑ๋ถ„ํฌ๋ฅผ ๋”ฐ๋ฅด๋Š”์ง€ ํ™•์ธ

๐Ÿ’ก ํ•ต์‹ฌ ์งˆ๋ฌธ: โ€œ๊ด€์ธก๋œ ๋นˆ๋„๊ฐ€ ๊ธฐ๋Œ€ํ•œ ์ด๋ก ์  ๋ถ„ํฌ์™€ ์ผ์น˜ํ•˜๋Š”๊ฐ€?โ€

# Titanic: ๊ฐ์‹ค ๋“ฑ๊ธ‰ ๋ถ„ํฌ๊ฐ€ ๊ท ๋“ฑํ•œ์ง€ ๊ฒ€์ • # ์ƒํ™ฉ: ํƒ€์ดํƒ€๋‹‰ํ˜ธ ์Šน๊ฐ์ด 1,2,3๋“ฑ๊ธ‰์— ๊ท ๋“ฑํ•˜๊ฒŒ ๋ถ„ํฌ๋˜์–ด ์žˆ์—ˆ๋Š”์ง€ ํ™•์ธ observed = titanic['pclass'].value_counts().sort_index() n = len(titanic) expected = np.array([n/3, n/3, n/3]) # ๊ท ๋“ฑ ๋ถ„ํฌ ๊ธฐ๋Œ€ chi2, p_value = stats.chisquare(observed, expected) print("=== ์นด์ด์ œ๊ณฑ ์ ํ•ฉ๋„ ๊ฒ€์ • ===") print(f"Hโ‚€: ๊ฐ์‹ค ๋“ฑ๊ธ‰์€ ๊ท ๋“ฑํ•˜๊ฒŒ ๋ถ„ํฌ๋˜์–ด ์žˆ๋‹ค (๊ฐ 33.3%)") print(f"Hโ‚: ๊ท ๋“ฑํ•˜์ง€ ์•Š๋‹ค") print(f"\n๊ด€์ธก ๋นˆ๋„:") for cls, count in observed.items(): print(f" {cls}๋“ฑ์„: {count}๋ช… ({count/n*100:.1f}%)") print(f"\n๊ธฐ๋Œ€ ๋นˆ๋„ (๊ท ๋“ฑ ๋ถ„ํฌ): ๊ฐ {n/3:.0f}๋ช… (33.3%)") print(f"\nฯ‡ยฒ ํ†ต๊ณ„๋Ÿ‰: {chi2:.4f}") print(f"p-value: {p_value:.6f}") print(f"\n๊ฒฐ๋ก : {'๊ท ๋“ฑํ•˜์ง€ ์•Š์Œ - 3๋“ฑ์„์ด ๊ณผ๋ฐ˜' if p_value < 0.05 else '๊ท ๋“ฑ ๋ถ„ํฌ'}")
์‹คํ–‰ ๊ฒฐ๊ณผ
=== ์นด์ด์ œ๊ณฑ ์ ํ•ฉ๋„ ๊ฒ€์ • ===
Hโ‚€: ๊ฐ์‹ค ๋“ฑ๊ธ‰์€ ๊ท ๋“ฑํ•˜๊ฒŒ ๋ถ„ํฌ๋˜์–ด ์žˆ๋‹ค (๊ฐ 33.3%)
Hโ‚: ๊ท ๋“ฑํ•˜์ง€ ์•Š๋‹ค

๊ด€์ธก ๋นˆ๋„:
1๋“ฑ์„: 216๋ช… (24.2%)
2๋“ฑ์„: 184๋ช… (20.7%)
3๋“ฑ์„: 491๋ช… (55.1%)

๊ธฐ๋Œ€ ๋นˆ๋„ (๊ท ๋“ฑ ๋ถ„ํฌ): ๊ฐ 297๋ช… (33.3%)

ฯ‡ยฒ ํ†ต๊ณ„๋Ÿ‰: 110.8417
p-value: 0.000000

๊ฒฐ๋ก : ๊ท ๋“ฑํ•˜์ง€ ์•Š์Œ - 3๋“ฑ์„์ด ๊ณผ๋ฐ˜

Fisherโ€™s Exact Test

๐Ÿ“Œ ์‚ฌ์šฉ ์ƒํ™ฉ ์˜ˆ์‹œ

  • ์ž„์ƒ์‹œํ—˜: ์†Œ๊ทœ๋ชจ ํŒŒ์ผ๋Ÿฟ ์—ฐ๊ตฌ(n < 20)์—์„œ ์น˜๋ฃŒ ํšจ๊ณผ ๊ฒ€์ •
  • ํฌ๊ท€ ์งˆํ™˜: ๋ฐœ์ƒ ๋นˆ๋„๊ฐ€ ๋‚ฎ์€ ํฌ๊ท€ ์งˆํ™˜๊ณผ ์œ ์ „์ž ๋ณ€์ด์˜ ์—ฐ๊ด€์„ฑ
  • ํ’ˆ์งˆ๊ด€๋ฆฌ: ๊ธฐ๋Œ€๋นˆ๋„๊ฐ€ 5 ๋ฏธ๋งŒ์ธ ํฌ๊ท€ ๋ถˆ๋Ÿ‰ ์œ ํ˜• ๋ถ„์„
  • ์—ญํ•™์กฐ์‚ฌ: ์†Œ๊ทœ๋ชจ ์ง‘๋‹จ์—์„œ ๊ฐ์—ผ ์—ฌ๋ถ€์™€ ํŠน์ • ํ–‰๋™์˜ ์—ฐ๊ด€์„ฑ

๐Ÿ’ก ํ•ต์‹ฌ ์งˆ๋ฌธ: โ€œ2ร—2 ๊ต์ฐจํ‘œ์—์„œ ์†Œํ‘œ๋ณธ์ผ ๋•Œ ๋‘ ๋ณ€์ˆ˜๊ฐ€ ์—ฐ๊ด€๋˜์–ด ์žˆ๋Š”๊ฐ€?โ€

โš ๏ธ ์นด์ด์ œ๊ณฑ ๊ฒ€์ •์˜ ๋Œ€์•ˆ: ๊ธฐ๋Œ€๋นˆ๋„๊ฐ€ 5 ๋ฏธ๋งŒ์ธ ์…€์ด ์žˆ์œผ๋ฉด Fisherโ€™s Exact ์‚ฌ์šฉ ๊ถŒ์žฅ

# ์†Œ๊ทœ๋ชจ ์ž„์ƒ์‹œํ—˜ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ # ์ƒํ™ฉ: 20๋ช… ๋Œ€์ƒ ํŒŒ์ผ๋Ÿฟ ์—ฐ๊ตฌ. ์‹ ์•ฝ ํˆฌ์—ฌ๊ตฐ(10๋ช…)๊ณผ ์œ„์•ฝ๊ตฐ(10๋ช…)์˜ ์™„์น˜์œจ ๋น„๊ต contingency = np.array([[8, 2], # ์น˜๋ฃŒ๊ตฐ: ์™„์น˜ 8, ๋ฏธ์™„์น˜ 2 [3, 7]]) # ๋Œ€์กฐ๊ตฐ: ์™„์น˜ 3, ๋ฏธ์™„์น˜ 7 odds_ratio, p_value = fisher_exact(contingency) print("=== Fisher's Exact Test ===") print("์ƒํ™ฉ: ์†Œ๊ทœ๋ชจ ์ž„์ƒ์‹œํ—˜ (n=20)") print("\n๊ต์ฐจํ‘œ:") print(" ์™„์น˜ ๋ฏธ์™„์น˜") print(f"์น˜๋ฃŒ๊ตฐ {contingency[0,0]} {contingency[0,1]}") print(f"๋Œ€์กฐ๊ตฐ {contingency[1,0]} {contingency[1,1]}") print(f"\n์น˜๋ฃŒ๊ตฐ ์™„์น˜์œจ: {contingency[0,0]/contingency[0].sum()*100:.0f}%") print(f"๋Œ€์กฐ๊ตฐ ์™„์น˜์œจ: {contingency[1,0]/contingency[1].sum()*100:.0f}%") print(f"\nOdds Ratio: {odds_ratio:.4f}") print(f"p-value: {p_value:.4f}") print(f"\n๊ฒฐ๋ก : {'์น˜๋ฃŒ ํšจ๊ณผ ์žˆ์Œ' if p_value < 0.05 else '์น˜๋ฃŒ ํšจ๊ณผ ์—†์Œ'}") print(f"\nํ•ด์„: ์น˜๋ฃŒ๊ตฐ์ด ๋Œ€์กฐ๊ตฐ๋ณด๋‹ค ์™„์น˜ odds๊ฐ€ {odds_ratio:.1f}๋ฐฐ ๋†’์Œ")
์‹คํ–‰ ๊ฒฐ๊ณผ
=== Fisher's Exact Test ===
์ƒํ™ฉ: ์†Œ๊ทœ๋ชจ ์ž„์ƒ์‹œํ—˜ (n=20)

๊ต์ฐจํ‘œ:
       ์™„์น˜  ๋ฏธ์™„์น˜
์น˜๋ฃŒ๊ตฐ     8      2
๋Œ€์กฐ๊ตฐ     3      7

์น˜๋ฃŒ๊ตฐ ์™„์น˜์œจ: 80%
๋Œ€์กฐ๊ตฐ ์™„์น˜์œจ: 30%

Odds Ratio: 9.3333
p-value: 0.0350

๊ฒฐ๋ก : ์น˜๋ฃŒ ํšจ๊ณผ ์žˆ์Œ

ํ•ด์„: ์น˜๋ฃŒ๊ตฐ์ด ๋Œ€์กฐ๊ตฐ๋ณด๋‹ค ์™„์น˜ odds๊ฐ€ 9.3๋ฐฐ ๋†’์Œ

McNemarโ€™s Test

๐Ÿ“Œ ์‚ฌ์šฉ ์ƒํ™ฉ ์˜ˆ์‹œ

  • ๋งˆ์ผ€ํŒ…: ๊ด‘๊ณ  ์บ ํŽ˜์ธ ์ „ํ›„ ๊ฐ™์€ ๊ณ ๊ฐ์˜ ๋ธŒ๋žœ๋“œ ์ธ์ง€ ๋ณ€ํ™” (์ธ์ง€Oโ†’์ธ์ง€O, ์ธ์ง€Xโ†’์ธ์ง€O ๋“ฑ)
  • ์˜ํ•™: ๊ฐ™์€ ํ™˜์ž์˜ ์น˜๋ฃŒ ์ „ํ›„ ์ฆ์ƒ ์œ ๋ฌด ๋ณ€ํ™”
  • ์ •์น˜: ๊ฐ™์€ ์œ ๊ถŒ์ž์˜ ์„ ๊ฑฐ ์ „ํ›„ ์ง€์ง€ ์ •๋‹น ๋ณ€ํ™”
  • ๊ต์œก: ๊ฐ™์€ ํ•™์ƒ์˜ ์ˆ˜์—… ์ „ํ›„ ํŠน์ • ๊ฐœ๋… ์ดํ•ด ์—ฌ๋ถ€ ๋ณ€ํ™”

๐Ÿ’ก ํ•ต์‹ฌ ์งˆ๋ฌธ: โ€œ๊ฐ™์€ ๋Œ€์ƒ์˜ ๋ฒ”์ฃผํ˜• ๋ฐ˜์‘์ด ์ „ํ›„๋กœ ๋‹ฌ๋ผ์กŒ๋Š”๊ฐ€?โ€

โš ๏ธ ๋Œ€์‘ํ‘œ๋ณธ + ๋ฒ”์ฃผํ˜• ๋ฐ์ดํ„ฐ์ผ ๋•Œ ์‚ฌ์šฉ. ์—ฐ์†ํ˜•์ด๋ฉด Wilcoxon/๋Œ€์‘ t-๊ฒ€์ • ์‚ฌ์šฉ.

from statsmodels.stats.contingency_tables import mcnemar # ๋งˆ์ผ€ํŒ… ์บ ํŽ˜์ธ ์ „ํ›„ ๊ตฌ๋งค ํ–‰๋™ ๋ณ€ํ™” # ์ƒํ™ฉ: 100๋ช…์˜ ๊ณ ๊ฐ์„ ๋Œ€์ƒ์œผ๋กœ ์บ ํŽ˜์ธ ์ „ํ›„ ๊ตฌ๋งค ์—ฌ๋ถ€๋ฅผ ์ถ”์  # [์บ ํŽ˜์ธ ์ „ ๊ตฌ๋งคO/ํ›„ ๊ตฌ๋งคO, ์ „ ๊ตฌ๋งคO/ํ›„ ๊ตฌ๋งคX] # [์บ ํŽ˜์ธ ์ „ ๊ตฌ๋งคX/ํ›„ ๊ตฌ๋งคO, ์ „ ๊ตฌ๋งคX/ํ›„ ๊ตฌ๋งคX] table = np.array([[45, 15], # ์ „์—๋„ ๊ตฌ๋งค, ํ›„์—๋„ ๊ตฌ๋งค / ์ „์— ๊ตฌ๋งค, ํ›„์— ๋ฏธ๊ตฌ๋งค [35, 5]]) # ์ „์— ๋ฏธ๊ตฌ๋งค, ํ›„์— ๊ตฌ๋งค / ์ „์—๋„ ๋ฏธ๊ตฌ๋งค, ํ›„์—๋„ ๋ฏธ๊ตฌ๋งค result = mcnemar(table, exact=True) print("=== McNemar's Test ===") print("์ƒํ™ฉ: 100๋ช… ๊ณ ๊ฐ์˜ ์บ ํŽ˜์ธ ์ „ํ›„ ๊ตฌ๋งค ํ–‰๋™ ๋ณ€ํ™”") print("\n๋Œ€์‘ํ‘œ:") print(" ์บ ํŽ˜์ธ ํ›„ ๊ตฌ๋งคO ์บ ํŽ˜์ธ ํ›„ ๊ตฌ๋งคX") print(f"์บ ํŽ˜์ธ ์ „ ๊ตฌ๋งคO {table[0,0]} {table[0,1]}") print(f"์บ ํŽ˜์ธ ์ „ ๊ตฌ๋งคX {table[1,0]} {table[1,1]}") print(f"\n๋ณ€ํ™” ๋ถ„์„:") print(f" โœ“ ๊ตฌ๋งคX โ†’ ๊ตฌ๋งคO (์‹ ๊ทœ ๊ตฌ๋งค): {table[1,0]}๋ช…") print(f" โœ— ๊ตฌ๋งคO โ†’ ๊ตฌ๋งคX (์ดํƒˆ): {table[0,1]}๋ช…") print(f" = ๋ณ€ํ™” ์—†์Œ: {table[0,0] + table[1,1]}๋ช…") print(f"\np-value: {result.pvalue:.4f}") print(f"\n๊ฒฐ๋ก : {'์บ ํŽ˜์ธ์ด ๊ตฌ๋งค ํ–‰๋™์„ ์œ ์˜ํ•˜๊ฒŒ ๋ณ€ํ™”์‹œํ‚ด (์‹ ๊ทœ ๊ตฌ๋งค > ์ดํƒˆ)' if result.pvalue < 0.05 else '์œ ์˜ํ•œ ๋ณ€ํ™” ์—†์Œ'}")
์‹คํ–‰ ๊ฒฐ๊ณผ
=== McNemar's Test ===
์ƒํ™ฉ: 100๋ช… ๊ณ ๊ฐ์˜ ์บ ํŽ˜์ธ ์ „ํ›„ ๊ตฌ๋งค ํ–‰๋™ ๋ณ€ํ™”

๋Œ€์‘ํ‘œ:
            ์บ ํŽ˜์ธ ํ›„ ๊ตฌ๋งคO  ์บ ํŽ˜์ธ ํ›„ ๊ตฌ๋งคX
์บ ํŽ˜์ธ ์ „ ๊ตฌ๋งคO      45            15
์บ ํŽ˜์ธ ์ „ ๊ตฌ๋งคX      35             5

๋ณ€ํ™” ๋ถ„์„:
โœ“ ๊ตฌ๋งคX โ†’ ๊ตฌ๋งคO (์‹ ๊ทœ ๊ตฌ๋งค): 35๋ช…
โœ— ๊ตฌ๋งคO โ†’ ๊ตฌ๋งคX (์ดํƒˆ): 15๋ช…
= ๋ณ€ํ™” ์—†์Œ: 50๋ช…

p-value: 0.0066

๊ฒฐ๋ก : ์บ ํŽ˜์ธ์ด ๊ตฌ๋งค ํ–‰๋™์„ ์œ ์˜ํ•˜๊ฒŒ ๋ณ€ํ™”์‹œํ‚ด (์‹ ๊ทœ ๊ตฌ๋งค > ์ดํƒˆ)

8. ์ƒ๊ด€๋ถ„์„ (Correlation Analysis)

Pearson ์ƒ๊ด€๊ณ„์ˆ˜

๐Ÿ“Œ ์‚ฌ์šฉ ์ƒํ™ฉ ์˜ˆ์‹œ

  • ๋งˆ์ผ€ํŒ…: ๊ด‘๊ณ ๋น„ ์ง€์ถœ๊ณผ ๋งค์ถœ์˜ ์„ ํ˜•์  ๊ด€๊ณ„ ๋ถ„์„
  • HR: ๊ทผ์† ์—ฐ์ˆ˜์™€ ์—ฐ๋ด‰์˜ ์ƒ๊ด€๊ด€๊ณ„
  • ๊ต์œก: ๊ณต๋ถ€ ์‹œ๊ฐ„๊ณผ ์‹œํ—˜ ์ ์ˆ˜์˜ ๊ด€๊ณ„
  • ๊ธˆ์œต: ๊ธˆ๋ฆฌ์™€ ์ฃผ๊ฐ€์˜ ๊ด€๊ณ„

๐Ÿ’ก ํ•ต์‹ฌ ์งˆ๋ฌธ: โ€œ๋‘ ์—ฐ์†ํ˜• ๋ณ€์ˆ˜ ๊ฐ„์— ์„ ํ˜•์  ๊ด€๊ณ„๊ฐ€ ์žˆ๋Š”๊ฐ€?โ€

โš ๏ธ ์ „์ œ์กฐ๊ฑด: ๋‘ ๋ณ€์ˆ˜ ๋ชจ๋‘ ์ •๊ทœ๋ถ„ํฌ, ์„ ํ˜• ๊ด€๊ณ„. ๋น„์„ ํ˜• ๊ด€๊ณ„๋Š” ๊ฐ์ง€ ๋ชปํ•จ.

# Diamonds: ์บ๋Ÿฟ๊ณผ ๊ฐ€๊ฒฉ์˜ ์ƒ๊ด€๊ด€๊ณ„ # ์ƒํ™ฉ: ๋‹ค์ด์•„๋ชฌ๋“œ ์บ๋Ÿฟ(๋ฌด๊ฒŒ)๊ณผ ๊ฐ€๊ฒฉ ์‚ฌ์ด์— ์„ ํ˜•์  ๊ด€๊ณ„๊ฐ€ ์žˆ๋Š”์ง€ ๋ถ„์„ carat = diamonds['carat'] price = diamonds['price'] r, p_value = pearsonr(carat, price) print("=== Pearson ์ƒ๊ด€๋ถ„์„ ===") print(f"Hโ‚€: ์บ๋Ÿฟ๊ณผ ๊ฐ€๊ฒฉ์€ ์ƒ๊ด€์ด ์—†๋‹ค (ฯ = 0)") print(f"Hโ‚: ์บ๋Ÿฟ๊ณผ ๊ฐ€๊ฒฉ์€ ์ƒ๊ด€์ด ์žˆ๋‹ค (ฯ โ‰  0)") print(f"\nPearson r: {r:.4f}") print(f"p-value: {p_value:.6f}") print(f"๊ฒฐ์ •๊ณ„์ˆ˜ (Rยฒ): {r**2:.4f} โ†’ ๊ฐ€๊ฒฉ ๋ณ€๋™์˜ {r**2*100:.1f}%๋ฅผ ์บ๋Ÿฟ์œผ๋กœ ์„ค๋ช…") print(f"\n์ƒ๊ด€ ๊ฐ•๋„ ํ•ด์„:") print(f" |r| < 0.3: ์•ฝํ•œ ์ƒ๊ด€") print(f" 0.3 โ‰ค |r| < 0.7: ์ค‘๊ฐ„ ์ƒ๊ด€") print(f" |r| โ‰ฅ 0.7: ๊ฐ•ํ•œ ์ƒ๊ด€") print(f"\nํ˜„์žฌ |r| = {abs(r):.4f} โ†’ ๊ฐ•ํ•œ ์–‘์˜ ์ƒ๊ด€ (์บ๋Ÿฟโ†‘ โ†’ ๊ฐ€๊ฒฉโ†‘)")
์‹คํ–‰ ๊ฒฐ๊ณผ
=== Pearson ์ƒ๊ด€๋ถ„์„ ===
Hโ‚€: ์บ๋Ÿฟ๊ณผ ๊ฐ€๊ฒฉ์€ ์ƒ๊ด€์ด ์—†๋‹ค (ฯ = 0)
Hโ‚: ์บ๋Ÿฟ๊ณผ ๊ฐ€๊ฒฉ์€ ์ƒ๊ด€์ด ์žˆ๋‹ค (ฯ โ‰  0)

Pearson r: 0.9209
p-value: 0.000000
๊ฒฐ์ •๊ณ„์ˆ˜ (Rยฒ): 0.8481 โ†’ ๊ฐ€๊ฒฉ ๋ณ€๋™์˜ 84.8%๋ฅผ ์บ๋Ÿฟ์œผ๋กœ ์„ค๋ช…

์ƒ๊ด€ ๊ฐ•๋„ ํ•ด์„:
|r| < 0.3: ์•ฝํ•œ ์ƒ๊ด€
0.3 โ‰ค |r| < 0.7: ์ค‘๊ฐ„ ์ƒ๊ด€
|r| โ‰ฅ 0.7: ๊ฐ•ํ•œ ์ƒ๊ด€

ํ˜„์žฌ |r| = 0.9209 โ†’ ๊ฐ•ํ•œ ์–‘์˜ ์ƒ๊ด€ (์บ๋Ÿฟโ†‘ โ†’ ๊ฐ€๊ฒฉโ†‘)

Spearman ์ˆœ์œ„์ƒ๊ด€๊ณ„์ˆ˜

๐Ÿ“Œ ์‚ฌ์šฉ ์ƒํ™ฉ ์˜ˆ์‹œ

  • ์„ค๋ฌธ์กฐ์‚ฌ: ๋งŒ์กฑ๋„ ์ˆœ์œ„์™€ ์žฌ๊ตฌ๋งค ์˜ํ–ฅ ์ˆœ์œ„์˜ ๊ด€๊ณ„
  • ๊ฒฝ์ œ: GDP ์ˆœ์œ„์™€ ํ–‰๋ณต์ง€์ˆ˜ ์ˆœ์œ„์˜ ๊ด€๊ณ„
  • ๊ต์œก: ํ•™์—… ์„ฑ์  ์ˆœ์œ„์™€ ์ทจ์—…๋ฅ  ์ˆœ์œ„์˜ ๊ด€๊ณ„
  • ์Šคํฌ์ธ : ์—ฐ๋ด‰ ์ˆœ์œ„์™€ ์„ฑ์  ์ˆœ์œ„์˜ ๊ด€๊ณ„

๐Ÿ’ก ํ•ต์‹ฌ ์งˆ๋ฌธ: โ€œ๋‘ ๋ณ€์ˆ˜ ๊ฐ„์— ๋‹จ์กฐ์ (monotonic) ๊ด€๊ณ„๊ฐ€ ์žˆ๋Š”๊ฐ€?โ€

โš ๏ธ Pearson์˜ ๋น„๋ชจ์ˆ˜ ๋Œ€์•ˆ: ์ •๊ทœ๋ถ„ํฌ ๋ถˆํ•„์š”, ๋น„์„ ํ˜•์ด์ง€๋งŒ ๋‹จ์กฐ์ ์ธ ๊ด€๊ณ„๋„ ๊ฐ์ง€. ์˜ˆ: y = xยฒ (๋‹จ์กฐ ์ฆ๊ฐ€ ๊ตฌ๊ฐ„์—์„œ๋Š” Spearman์ด ๋†’์Œ)

# Tips: ์ด ๊ฒฐ์ œ ๊ธˆ์•ก๊ณผ ํŒ์˜ ์ˆœ์œ„ ์ƒ๊ด€ # ์ƒํ™ฉ: ๊ฒฐ์ œ ๊ธˆ์•ก์ด ๋†’์„์ˆ˜๋ก ํŒ๋„ ๋†’์€ ๊ฒฝํ–ฅ์ด ์žˆ๋Š”์ง€ (์ •ํ™•ํ•œ ๋น„๋ก€๊ฐ€ ์•„๋‹ˆ๋”๋ผ๋„) total_bill = tips['total_bill'] tip = tips['tip'] rho, p_value = spearmanr(total_bill, tip) r_pearson, _ = pearsonr(total_bill, tip) print("=== Spearman ์ˆœ์œ„ ์ƒ๊ด€๋ถ„์„ ===") print(f"Hโ‚€: ๊ฒฐ์ œ ๊ธˆ์•ก๊ณผ ํŒ์€ ๋‹จ์กฐ์  ๊ด€๊ณ„๊ฐ€ ์—†๋‹ค") print(f"Hโ‚: ๊ฒฐ์ œ ๊ธˆ์•ก๊ณผ ํŒ์€ ๋‹จ์กฐ์  ๊ด€๊ณ„๊ฐ€ ์žˆ๋‹ค") print(f"\nSpearman ฯ: {rho:.4f}") print(f"(๋น„๊ต) Pearson r: {r_pearson:.4f}") print(f"p-value: {p_value:.6f}") print(f"\n๊ฒฐ๋ก : {'์œ ์˜ํ•œ ๋‹จ์กฐ ๊ด€๊ณ„ - ๊ฒฐ์ œ์•ก์ด ๋†’์œผ๋ฉด ํŒ๋„ ๋†’์€ ๊ฒฝํ–ฅ' if p_value < 0.05 else '๊ด€๊ณ„ ์—†์Œ'}")
์‹คํ–‰ ๊ฒฐ๊ณผ
=== Spearman ์ˆœ์œ„ ์ƒ๊ด€๋ถ„์„ ===
Hโ‚€: ๊ฒฐ์ œ ๊ธˆ์•ก๊ณผ ํŒ์€ ๋‹จ์กฐ์  ๊ด€๊ณ„๊ฐ€ ์—†๋‹ค
Hโ‚: ๊ฒฐ์ œ ๊ธˆ์•ก๊ณผ ํŒ์€ ๋‹จ์กฐ์  ๊ด€๊ณ„๊ฐ€ ์žˆ๋‹ค

Spearman ฯ: 0.8264
(๋น„๊ต) Pearson r: 0.6757
p-value: 0.000000

๊ฒฐ๋ก : ์œ ์˜ํ•œ ๋‹จ์กฐ ๊ด€๊ณ„ - ๊ฒฐ์ œ์•ก์ด ๋†’์œผ๋ฉด ํŒ๋„ ๋†’์€ ๊ฒฝํ–ฅ

Kendallโ€™s Tau

๐Ÿ“Œ ์‚ฌ์šฉ ์ƒํ™ฉ ์˜ˆ์‹œ

  • ์ˆœ์œ„ ๋ฐ์ดํ„ฐ: ๋‘ ์‹ฌ์‚ฌ์œ„์›์˜ ์ˆœ์œ„ ํ‰๊ฐ€ ์ผ์น˜๋„ (์˜ˆ: ๋ง›์ง‘ ์ˆœ์œ„)
  • ์„œ์—ด ์ฒ™๋„: ๊ต์œก ์ˆ˜์ค€(์ดˆ์กธ/์ค‘์กธ/๊ณ ์กธ/๋Œ€์กธ)๊ณผ ์†Œ๋“ ์ˆ˜์ค€(ํ•˜/์ค‘/์ƒ)์˜ ๊ด€๊ณ„
  • ๋™์ˆœ์œ„๊ฐ€ ๋งŽ์„ ๋•Œ: 5์  ์ฒ™๋„ ์„ค๋ฌธ์ฒ˜๋Ÿผ ๊ฐ™์€ ๊ฐ’์ด ๋งŽ์€ ๋ฐ์ดํ„ฐ

๐Ÿ’ก ํ•ต์‹ฌ ์งˆ๋ฌธ: โ€œ์ˆœ์œ„ ๋ฐ์ดํ„ฐ์—์„œ ๋‘ ๋ณ€์ˆ˜์˜ **์ผ์น˜๋„(concordance)**๋Š” ์–ผ๋งˆ์ธ๊ฐ€?โ€

โš ๏ธ Spearman๋ณด๋‹ค ๋ณด์ˆ˜์ . ๋™์ˆœ์œ„(ties)๊ฐ€ ๋งŽ์„ ๋•Œ ๋” ์ •ํ™•.

# Titanic: ๊ฐ์‹ค ๋“ฑ๊ธ‰๊ณผ ๋‚˜์ด์˜ ๊ด€๊ณ„ # ์ƒํ™ฉ: 1๋“ฑ์„ ์Šน๊ฐ์ด ๋” ๋‚˜์ด๊ฐ€ ๋งŽ์€ ๊ฒฝํ–ฅ์ด ์žˆ๋Š”์ง€ (์„œ์—ด vs ์—ฐ์†) pclass = titanic['pclass'].dropna() age = titanic['age'].dropna() # ์ธ๋ฑ์Šค ๋งž์ถ”๊ธฐ common_idx = pclass.index.intersection(age.index) pclass_aligned = pclass.loc[common_idx] age_aligned = age.loc[common_idx] tau, p_value = kendalltau(pclass_aligned, age_aligned) print("=== Kendall's Tau ์ƒ๊ด€๋ถ„์„ ===") print(f"Hโ‚€: ๊ฐ์‹ค ๋“ฑ๊ธ‰๊ณผ ๋‚˜์ด๋Š” ๊ด€๊ณ„๊ฐ€ ์—†๋‹ค") print(f"Hโ‚: ๊ฐ์‹ค ๋“ฑ๊ธ‰๊ณผ ๋‚˜์ด๋Š” ๊ด€๊ณ„๊ฐ€ ์žˆ๋‹ค") print(f"\nKendall ฯ„: {tau:.4f}") print(f"p-value: {p_value:.4f}") print(f"\n๊ฒฐ๋ก : {'์œ ์˜ํ•œ ๊ด€๊ณ„' if p_value < 0.05 else '๊ด€๊ณ„ ์—†์Œ'}") if tau < 0: print(f"ํ•ด์„: ฯ„ < 0 ์ด๋ฏ€๋กœ ๊ฐ์‹ค ๋“ฑ๊ธ‰โ†“(1๋“ฑ๊ธ‰) โ†’ ๋‚˜์ดโ†‘ (๊ณ ๊ธ‰ ๊ฐ์‹ค์— ๋‚˜์ด ๋งŽ์€ ์Šน๊ฐ)")
์‹คํ–‰ ๊ฒฐ๊ณผ
=== Kendall's Tau ์ƒ๊ด€๋ถ„์„ ===
Hโ‚€: ๊ฐ์‹ค ๋“ฑ๊ธ‰๊ณผ ๋‚˜์ด๋Š” ๊ด€๊ณ„๊ฐ€ ์—†๋‹ค
Hโ‚: ๊ฐ์‹ค ๋“ฑ๊ธ‰๊ณผ ๋‚˜์ด๋Š” ๊ด€๊ณ„๊ฐ€ ์žˆ๋‹ค

Kendall ฯ„: -0.1080
p-value: 0.0000

๊ฒฐ๋ก : ์œ ์˜ํ•œ ๊ด€๊ณ„
ํ•ด์„: ฯ„ < 0 ์ด๋ฏ€๋กœ ๊ฐ์‹ค ๋“ฑ๊ธ‰โ†“(1๋“ฑ๊ธ‰) โ†’ ๋‚˜์ดโ†‘ (๊ณ ๊ธ‰ ๊ฐ์‹ค์— ๋‚˜์ด ๋งŽ์€ ์Šน๊ฐ)

9. ํšจ๊ณผ ํฌ๊ธฐ (Effect Size)

๐ŸŽฏ ์™œ ํšจ๊ณผ ํฌ๊ธฐ๊ฐ€ ์ค‘์š”ํ•œ๊ฐ€์š”?

p-value๋Š” โ€œ์ฐจ์ด๊ฐ€ ์žˆ๋Š”๊ฐ€?โ€๋งŒ ์•Œ๋ ค์ฃผ๊ณ , โ€œ์–ผ๋งˆ๋‚˜ ํฐ ์ฐจ์ด์ธ๊ฐ€?โ€๋Š” ์•Œ๋ ค์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ‘œ๋ณธ์ด ํฌ๋ฉด ์•„์ฃผ ์ž‘์€ ์ฐจ์ด๋„ ์œ ์˜ํ•˜๊ฒŒ ๋‚˜์˜ฌ ์ˆ˜ ์žˆ์–ด์š”.

์˜ˆ์‹œ: 100๋งŒ ๋ช… ๋Œ€์ƒ A/B ํ…Œ์ŠคํŠธ์—์„œ ์ „ํ™˜์œจ 0.01%p ์ฐจ์ด๋„ p < 0.05๊ฐ€ ๋  ์ˆ˜ ์žˆ์ง€๋งŒ, ์ด ์ฐจ์ด๊ฐ€ ์‹ค์ œ๋กœ ๋น„์ฆˆ๋‹ˆ์Šค์— ์˜๋ฏธ ์žˆ๋Š” ์ฐจ์ด์ธ์ง€๋Š” ํšจ๊ณผ ํฌ๊ธฐ๋กœ ํŒ๋‹จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Cohenโ€™s d

๐Ÿ“Œ ์‚ฌ์šฉ ์ƒํ™ฉ: ๋‘ ๊ทธ๋ฃน ํ‰๊ท  ์ฐจ์ด์˜ ์‹ค์งˆ์  ์˜๋ฏธ ํ•ด์„

ํ•ด์„ ๊ธฐ์ค€ (Cohen, 1988):

  • |d| < 0.2: ์ž‘์€ ํšจ๊ณผ (๋ฌด์‹œํ•ด๋„ ๋  ์ˆ˜์ค€)
  • 0.2 โ‰ค |d| < 0.5: ์ค‘๊ฐ„ ํšจ๊ณผ
  • 0.5 โ‰ค |d| < 0.8: ํฐ ํšจ๊ณผ
  • |d| โ‰ฅ 0.8: ๋งค์šฐ ํฐ ํšจ๊ณผ
def cohens_d(group1, group2): n1, n2 = len(group1), len(group2) var1, var2 = group1.var(), group2.var() pooled_std = np.sqrt(((n1-1)*var1 + (n2-1)*var2) / (n1+n2-2)) return (group1.mean() - group2.mean()) / pooled_std # Titanic: ์ƒ์กด์ž vs ์‚ฌ๋ง์ž ๋‚˜์ด ์ฐจ์ด์˜ ํšจ๊ณผ ํฌ๊ธฐ # ์ƒํ™ฉ: ๋‚˜์ด์™€ ์ƒ์กด์˜ ๊ด€๊ณ„. p-value๊ฐ€ ์œ ์˜ํ•ด๋„ ์‹ค์ œ๋กœ ์˜๋ฏธ ์žˆ๋Š” ์ฐจ์ด์ธ์ง€? survived_ages = titanic[titanic['survived'] == 1]['age'].dropna() died_ages = titanic[titanic['survived'] == 0]['age'].dropna() d = cohens_d(survived_ages, died_ages) t_stat, p_value = ttest_ind(survived_ages, died_ages) print("=== ํšจ๊ณผ ํฌ๊ธฐ ๋ถ„์„ ===") print(f"์ƒ์กด์ž ํ‰๊ท  ๋‚˜์ด: {survived_ages.mean():.2f}์„ธ") print(f"์‚ฌ๋ง์ž ํ‰๊ท  ๋‚˜์ด: {died_ages.mean():.2f}์„ธ") print(f"์ฐจ์ด: {abs(survived_ages.mean() - died_ages.mean()):.2f}์„ธ") print(f"\nt-ํ†ต๊ณ„๋Ÿ‰: {t_stat:.4f}") print(f"p-value: {p_value:.4f} โ†’ {'์œ ์˜ํ•จ' if p_value < 0.05 else '์œ ์˜ํ•˜์ง€ ์•Š์Œ'}") print(f"Cohen's d: {d:.4f}") print(f"\nํšจ๊ณผ ํฌ๊ธฐ ํ•ด์„:") print(f" |d| < 0.2: ์ž‘์€ ํšจ๊ณผ") print(f" 0.2 โ‰ค |d| < 0.5: ์ค‘๊ฐ„ ํšจ๊ณผ") print(f" 0.5 โ‰ค |d| < 0.8: ํฐ ํšจ๊ณผ") print(f" |d| โ‰ฅ 0.8: ๋งค์šฐ ํฐ ํšจ๊ณผ") print(f"\nํ˜„์žฌ: |d| = {abs(d):.4f} โ†’ ", end="") if abs(d) >= 0.8: print("๋งค์šฐ ํฐ ํšจ๊ณผ") elif abs(d) >= 0.5: print("ํฐ ํšจ๊ณผ") elif abs(d) >= 0.2: print("์ค‘๊ฐ„ ํšจ๊ณผ") else: print("์ž‘์€ ํšจ๊ณผ โ†’ ํ†ต๊ณ„์ ์œผ๋กœ ์œ ์˜ํ•˜์ง€๋งŒ ์‹ค์งˆ์  ์˜๋ฏธ๋Š” ์ œํ•œ์ !")
์‹คํ–‰ ๊ฒฐ๊ณผ
=== ํšจ๊ณผ ํฌ๊ธฐ ๋ถ„์„ ===
์ƒ์กด์ž ํ‰๊ท  ๋‚˜์ด: 28.34์„ธ
์‚ฌ๋ง์ž ํ‰๊ท  ๋‚˜์ด: 30.63์„ธ
์ฐจ์ด: 2.29์„ธ

t-ํ†ต๊ณ„๋Ÿ‰: -2.0551
p-value: 0.0402 โ†’ ์œ ์˜ํ•จ
Cohen's d: -0.1616

ํšจ๊ณผ ํฌ๊ธฐ ํ•ด์„:
|d| < 0.2: ์ž‘์€ ํšจ๊ณผ
0.2 โ‰ค |d| < 0.5: ์ค‘๊ฐ„ ํšจ๊ณผ
0.5 โ‰ค |d| < 0.8: ํฐ ํšจ๊ณผ
|d| โ‰ฅ 0.8: ๋งค์šฐ ํฐ ํšจ๊ณผ

ํ˜„์žฌ: |d| = 0.1616 โ†’ ์ž‘์€ ํšจ๊ณผ โ†’ ํ†ต๊ณ„์ ์œผ๋กœ ์œ ์˜ํ•˜์ง€๋งŒ ์‹ค์งˆ์  ์˜๋ฏธ๋Š” ์ œํ•œ์ !

Cramรฉrโ€™s V

๐Ÿ“Œ ์‚ฌ์šฉ ์ƒํ™ฉ: ๋ฒ”์ฃผํ˜• ๋ณ€์ˆ˜ ๊ฐ„ ์—ฐ๊ด€์„ฑ ๊ฐ•๋„ ์ธก์ • (์นด์ด์ œ๊ณฑ ๊ฒ€์ • ํ›„)

ํ•ด์„ ๊ธฐ์ค€:

  • V < 0.1: ๋ฌด์‹œํ•  ์ˆ˜์ค€
  • 0.1 โ‰ค V < 0.3: ์•ฝํ•œ ์—ฐ๊ด€
  • 0.3 โ‰ค V < 0.5: ์ค‘๊ฐ„ ์—ฐ๊ด€
  • V โ‰ฅ 0.5: ๊ฐ•ํ•œ ์—ฐ๊ด€
def cramers_v(contingency_table): chi2 = chi2_contingency(contingency_table)[0] n = contingency_table.sum().sum() min_dim = min(contingency_table.shape) - 1 return np.sqrt(chi2 / (n * min_dim)) # Titanic: ์„ฑ๋ณ„๊ณผ ์ƒ์กด์˜ ์—ฐ๊ด€ ๊ฐ•๋„ contingency = pd.crosstab(titanic['sex'], titanic['survived']) v = cramers_v(contingency) chi2, p_value, _, _ = chi2_contingency(contingency) print("=== Cramรฉr's V (์—ฐ๊ด€์„ฑ ๊ฐ•๋„) ===") print(f"ฯ‡ยฒ = {chi2:.4f}, p-value = {p_value:.6f}") print(f"Cramรฉr's V = {v:.4f}") print(f"\nํ•ด์„ ๊ธฐ์ค€:") print(f" V < 0.1: ๋ฌด์‹œํ•  ์ˆ˜์ค€") print(f" 0.1 โ‰ค V < 0.3: ์•ฝํ•œ ์—ฐ๊ด€") print(f" 0.3 โ‰ค V < 0.5: ์ค‘๊ฐ„ ์—ฐ๊ด€") print(f" V โ‰ฅ 0.5: ๊ฐ•ํ•œ ์—ฐ๊ด€") print(f"\nํ˜„์žฌ: V = {v:.4f} โ†’ ", end="") if v >= 0.5: print("๊ฐ•ํ•œ ์—ฐ๊ด€ โ†’ ์„ฑ๋ณ„์ด ์ƒ์กด์— ๋งค์šฐ ํฐ ์˜ํ–ฅ!") elif v >= 0.3: print("์ค‘๊ฐ„ ์—ฐ๊ด€") elif v >= 0.1: print("์•ฝํ•œ ์—ฐ๊ด€") else: print("๋ฌด์‹œํ•  ์ˆ˜์ค€")
์‹คํ–‰ ๊ฒฐ๊ณผ
=== Cramรฉr's V (์—ฐ๊ด€์„ฑ ๊ฐ•๋„) ===
ฯ‡ยฒ = 260.7170, p-value = 0.000000
Cramรฉr's V = 0.5410

ํ•ด์„ ๊ธฐ์ค€:
V < 0.1: ๋ฌด์‹œํ•  ์ˆ˜์ค€
0.1 โ‰ค V < 0.3: ์•ฝํ•œ ์—ฐ๊ด€
0.3 โ‰ค V < 0.5: ์ค‘๊ฐ„ ์—ฐ๊ด€
V โ‰ฅ 0.5: ๊ฐ•ํ•œ ์—ฐ๊ด€

ํ˜„์žฌ: V = 0.5410 โ†’ ๊ฐ•ํ•œ ์—ฐ๊ด€ โ†’ ์„ฑ๋ณ„์ด ์ƒ์กด์— ๋งค์šฐ ํฐ ์˜ํ–ฅ!

10. ๋‹ค์ค‘๊ฒ€์ • ๋ณด์ • (Multiple Testing Correction)

๐ŸŽฏ ์™œ ๋ณด์ •์ด ํ•„์š”ํ•œ๊ฐ€์š”?

์—ฌ๋Ÿฌ ๊ฒ€์ •์„ ๋™์‹œ์— ์ˆ˜ํ–‰ํ•˜๋ฉด **1์ข… ์˜ค๋ฅ˜(๊ฑฐ์ง“ ์–‘์„ฑ)**๊ฐ€ ๋ˆ„์ ๋ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ: ฮฑ = 0.05๋กœ 20๊ฐœ ๊ฒ€์ •์„ ํ•˜๋ฉด

  • ์ ์–ด๋„ 1๊ฐœ ๊ฑฐ์ง“ ์–‘์„ฑ ํ™•๋ฅ  = 1 - (0.95)^20 = 64%!

์ด๋ฅผ **๋‹ค์ค‘ ๋น„๊ต ๋ฌธ์ œ(Multiple Comparison Problem)**๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

Bonferroni Correction

๐Ÿ“Œ ์‚ฌ์šฉ ์ƒํ™ฉ:

  • ์—ฌ๋Ÿฌ A/B ํ…Œ์ŠคํŠธ๋ฅผ ๋™์‹œ์— ๋ถ„์„ํ•  ๋•Œ
  • ANOVA ํ›„ ์‚ฌํ›„๊ฒ€์ •์—์„œ ์—ฌ๋Ÿฌ ์Œ์„ ๋น„๊ตํ•  ๋•Œ
  • ์œ ์ „์ฒด ์—ฐ๊ตฌ์—์„œ ์ˆ˜์ฒœ ๊ฐœ์˜ ์œ ์ „์ž๋ฅผ ๊ฒ€์ •ํ•  ๋•Œ

๐Ÿ’ก ๋ฐฉ๋ฒ•: ฮฑ๋ฅผ ๊ฒ€์ • ํšŸ์ˆ˜(k)๋กœ ๋‚˜๋ˆ”. ์˜ˆ: 5๊ฐœ ๊ฒ€์ • ์‹œ 0.05/5 = 0.01

โš ๏ธ ๋งค์šฐ ๋ณด์ˆ˜์ . ์‹ค์ œ ํšจ๊ณผ๋„ ๋†“์น  ์ˆ˜ ์žˆ์Œ (2์ข… ์˜ค๋ฅ˜ ์ฆ๊ฐ€)

from statsmodels.stats.multitest import multipletests # ์—ฌ๋Ÿฌ A/B ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ # ์ƒํ™ฉ: 5๊ฐ€์ง€ UI ์š”์†Œ๋ฅผ ๋™์‹œ์— ํ…Œ์ŠคํŠธ. ์–ด๋–ค ๊ฒƒ์ด ์ง„์งœ ํšจ๊ณผ๊ฐ€ ์žˆ๋Š”์ง€? p_values = [0.03, 0.04, 0.01, 0.08, 0.002] test_names = ['๋ฒ„ํŠผ ์ƒ‰์ƒ', 'ํ—ค๋“œ๋ผ์ธ', 'CTA ์œ„์น˜', '์ด๋ฏธ์ง€', '๊ฐ€๊ฒฉ ํ‘œ์‹œ'] # Bonferroni ๋ณด์ • rejected, corrected_p, _, _ = multipletests(p_values, method='bonferroni') print("=== ๋‹ค์ค‘๊ฒ€์ • ๋ณด์ • (Bonferroni) ===") print(f"๊ฒ€์ • ์ˆ˜: {len(p_values)}") print(f"๋ณด์ •๋œ ์œ ์˜์ˆ˜์ค€: 0.05 / {len(p_values)} = {0.05/len(p_values):.3f}") print(f"\n{'ํ…Œ์ŠคํŠธ':<12} {'์›๋ž˜ p-value':<15} {'๋ณด์ • p-value':<15} {'๊ฒฐ๋ก '}") print("-" * 60) for name, p, cp, rej in zip(test_names, p_values, corrected_p, rejected): result = "โœ“ ์œ ์˜ํ•จ" if rej else "โœ— ์œ ์˜ํ•˜์ง€ ์•Š์Œ" print(f"{name:<12} {p:<15.4f} {min(cp, 1.0):<15.4f} {result}")
์‹คํ–‰ ๊ฒฐ๊ณผ
=== ๋‹ค์ค‘๊ฒ€์ • ๋ณด์ • (Bonferroni) ===
๊ฒ€์ • ์ˆ˜: 5
๋ณด์ •๋œ ์œ ์˜์ˆ˜์ค€: 0.05 / 5 = 0.010

ํ…Œ์ŠคํŠธ       ์›๋ž˜ p-value    ๋ณด์ • p-value    ๊ฒฐ๋ก 
------------------------------------------------------------
๋ฒ„ํŠผ ์ƒ‰์ƒ     0.0300          0.1500          โœ— ์œ ์˜ํ•˜์ง€ ์•Š์Œ
ํ—ค๋“œ๋ผ์ธ      0.0400          0.2000          โœ— ์œ ์˜ํ•˜์ง€ ์•Š์Œ
CTA ์œ„์น˜     0.0100          0.0500          โœ— ์œ ์˜ํ•˜์ง€ ์•Š์Œ
์ด๋ฏธ์ง€        0.0800          0.4000          โœ— ์œ ์˜ํ•˜์ง€ ์•Š์Œ
๊ฐ€๊ฒฉ ํ‘œ์‹œ     0.0020          0.0100          โœ“ ์œ ์˜ํ•จ

Benjamini-Hochberg (FDR)

๐Ÿ“Œ ์‚ฌ์šฉ ์ƒํ™ฉ:

  • ๋งŽ์€ ๊ฒ€์ •์„ ์ˆ˜ํ–‰ํ•˜์ง€๋งŒ ์ผ๋ถ€ ๊ฑฐ์ง“ ์–‘์„ฑ์€ ๊ฐ์ˆ˜ํ•  ์ˆ˜ ์žˆ์„ ๋•Œ
  • ํƒ์ƒ‰์  ๋ถ„์„์—์„œ ํ›„๋ณด๋ฅผ ์„ ๋ณ„ํ•  ๋•Œ
  • ์œ ์ „์ฒด ์—ฐ๊ตฌ์—์„œ Bonferroni๊ฐ€ ๋„ˆ๋ฌด ๋ณด์ˆ˜์ ์ผ ๋•Œ

๐Ÿ’ก ๋ฐฉ๋ฒ•: False Discovery Rate (FDR)๋ฅผ ์ œ์–ด. โ€œ์œ ์˜ํ•˜๋‹ค๊ณ  ํŒ์ •ํ•œ ๊ฒƒ ์ค‘ ๊ฑฐ์ง“ ์–‘์„ฑ ๋น„์œจโ€์„ 5%๋กœ ์ œ์–ด

# Benjamini-Hochberg ๋ณด์ • rejected_bh, corrected_p_bh, _, _ = multipletests(p_values, method='fdr_bh') print("=== ๋‹ค์ค‘๊ฒ€์ • ๋ณด์ • (Benjamini-Hochberg FDR) ===") print(f"\n{'ํ…Œ์ŠคํŠธ':<12} {'์›๋ž˜ p-value':<15} {'๋ณด์ • p-value':<15} {'๊ฒฐ๋ก '}") print("-" * 60) for name, p, cp, rej in zip(test_names, p_values, corrected_p_bh, rejected_bh): result = "โœ“ ์œ ์˜ํ•จ" if rej else "โœ— ์œ ์˜ํ•˜์ง€ ์•Š์Œ" print(f"{name:<12} {p:<15.4f} {cp:<15.4f} {result}") print(f"\n๋น„๊ต:") print(f" Bonferroni๋กœ ์œ ์˜: {sum(rejected)}๊ฐœ") print(f" FDR(BH)๋กœ ์œ ์˜: {sum(rejected_bh)}๊ฐœ") print(f"\nโ†’ FDR์ด ๋œ ๋ณด์ˆ˜์ ์ด์–ด์„œ ๋” ๋งŽ์€ ๋ฐœ๊ฒฌ ๊ฐ€๋Šฅ") print(f" ๋‹จ, ์ด ์ค‘ ์•ฝ 5%๋Š” ๊ฑฐ์ง“ ์–‘์„ฑ์ผ ์ˆ˜ ์žˆ์Œ")
์‹คํ–‰ ๊ฒฐ๊ณผ
=== ๋‹ค์ค‘๊ฒ€์ • ๋ณด์ • (Benjamini-Hochberg FDR) ===

ํ…Œ์ŠคํŠธ       ์›๋ž˜ p-value    ๋ณด์ • p-value    ๊ฒฐ๋ก 
------------------------------------------------------------
๋ฒ„ํŠผ ์ƒ‰์ƒ     0.0300          0.0500          โœ“ ์œ ์˜ํ•จ
ํ—ค๋“œ๋ผ์ธ      0.0400          0.0500          โœ“ ์œ ์˜ํ•จ
CTA ์œ„์น˜     0.0100          0.0250          โœ“ ์œ ์˜ํ•จ
์ด๋ฏธ์ง€        0.0800          0.0800          โœ— ์œ ์˜ํ•˜์ง€ ์•Š์Œ
๊ฐ€๊ฒฉ ํ‘œ์‹œ     0.0020          0.0100          โœ“ ์œ ์˜ํ•จ

๋น„๊ต:
Bonferroni๋กœ ์œ ์˜: 1๊ฐœ
FDR(BH)๋กœ ์œ ์˜: 4๊ฐœ

โ†’ FDR์ด ๋œ ๋ณด์ˆ˜์ ์ด์–ด์„œ ๋” ๋งŽ์€ ๋ฐœ๊ฒฌ ๊ฐ€๋Šฅ
 ๋‹จ, ์ด ์ค‘ ์•ฝ 5%๋Š” ๊ฑฐ์ง“ ์–‘์„ฑ์ผ ์ˆ˜ ์žˆ์Œ

11. ๊ฒ€์ •๋ ฅ ๋ถ„์„ (Power Analysis)

๐ŸŽฏ ์–ธ์ œ ์‚ฌ์šฉํ•˜๋‚˜์š”?

์‹คํ—˜ ์„ค๊ณ„ ๋‹จ๊ณ„์—์„œ โ€œ๋ช‡ ๋ช…์˜ ํ‘œ๋ณธ์ด ํ•„์š”ํ•œ๊ฐ€?โ€๋ฅผ ๊ณ„์‚ฐํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

ํ‘œ๋ณธ์ด ๋„ˆ๋ฌด ์ ์œผ๋ฉด ์‹ค์ œ ํšจ๊ณผ๊ฐ€ ์žˆ์–ด๋„ ํƒ์ง€ ๋ชปํ•˜๊ณ  (2์ข… ์˜ค๋ฅ˜), ํ‘œ๋ณธ์ด ๋„ˆ๋ฌด ๋งŽ์œผ๋ฉด ์ž์› ๋‚ญ๋น„์ž…๋‹ˆ๋‹ค.

from statsmodels.stats.power import TTestIndPower power_analysis = TTestIndPower() # ์‹œ๋‚˜๋ฆฌ์˜ค: ํšจ๊ณผ ํฌ๊ธฐ 0.3, ๊ฒ€์ •๋ ฅ 80%, ์œ ์˜์ˆ˜์ค€ 5% # ์ƒํ™ฉ: "์ƒˆ UI๊ฐ€ ์ „ํ™˜์œจ์„ ์ค‘๊ฐ„ ์ •๋„(d=0.3) ๋†’์ผ ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒ. # 80% ํ™•๋ฅ ๋กœ ์ด ํšจ๊ณผ๋ฅผ ํƒ์ง€ํ•˜๋ ค๋ฉด ๋ช‡ ๋ช…์ด ํ•„์š”ํ•œ๊ฐ€?" effect_size = 0.3 alpha = 0.05 power = 0.8 n = power_analysis.solve_power(effect_size=effect_size, alpha=alpha, power=power, ratio=1.0, alternative='two-sided') print("=== ํ‘œ๋ณธ ํฌ๊ธฐ ๊ณ„์‚ฐ ===") print(f"๋ชฉํ‘œ ํšจ๊ณผ ํฌ๊ธฐ (Cohen's d): {effect_size} (์ค‘๊ฐ„ ํšจ๊ณผ)") print(f"์œ ์˜์ˆ˜์ค€ (ฮฑ): {alpha}") print(f"๋ชฉํ‘œ ๊ฒ€์ •๋ ฅ (1-ฮฒ): {power} (80% ํ™•๋ฅ ๋กœ ํšจ๊ณผ ํƒ์ง€)") print(f"\nํ•„์š” ํ‘œ๋ณธ ํฌ๊ธฐ: ๊ทธ๋ฃน๋‹น {n:.0f}๋ช…") print(f"์ด ํ•„์š” ์ธ์›: {n*2:.0f}๋ช…") # ๋‹ค์–‘ํ•œ ํšจ๊ณผ ํฌ๊ธฐ์— ๋”ฐ๋ฅธ ํ•„์š” ํ‘œ๋ณธ ์ˆ˜ print("\nํšจ๊ณผ ํฌ๊ธฐ๋ณ„ ํ•„์š” ํ‘œ๋ณธ ์ˆ˜ (๊ฒ€์ •๋ ฅ 80%):") for es, desc in [(0.2, '์ž‘์€ ํšจ๊ณผ'), (0.3, '์ค‘๊ฐ„ ํšจ๊ณผ'), (0.5, 'ํฐ ํšจ๊ณผ'), (0.8, '๋งค์šฐ ํฐ ํšจ๊ณผ')]: n = power_analysis.solve_power(effect_size=es, alpha=0.05, power=0.8, ratio=1.0) print(f" d = {es} ({desc}): ๊ทธ๋ฃน๋‹น {n:.0f}๋ช… (์ด {n*2:.0f}๋ช…)")
์‹คํ–‰ ๊ฒฐ๊ณผ
=== ํ‘œ๋ณธ ํฌ๊ธฐ ๊ณ„์‚ฐ ===
๋ชฉํ‘œ ํšจ๊ณผ ํฌ๊ธฐ (Cohen's d): 0.3 (์ค‘๊ฐ„ ํšจ๊ณผ)
์œ ์˜์ˆ˜์ค€ (ฮฑ): 0.05
๋ชฉํ‘œ ๊ฒ€์ •๋ ฅ (1-ฮฒ): 0.8 (80% ํ™•๋ฅ ๋กœ ํšจ๊ณผ ํƒ์ง€)

ํ•„์š” ํ‘œ๋ณธ ํฌ๊ธฐ: ๊ทธ๋ฃน๋‹น 176๋ช…
์ด ํ•„์š” ์ธ์›: 352๋ช…

ํšจ๊ณผ ํฌ๊ธฐ๋ณ„ ํ•„์š” ํ‘œ๋ณธ ์ˆ˜ (๊ฒ€์ •๋ ฅ 80%):
d = 0.2 (์ž‘์€ ํšจ๊ณผ): ๊ทธ๋ฃน๋‹น 394๋ช… (์ด 787๋ช…)
d = 0.3 (์ค‘๊ฐ„ ํšจ๊ณผ): ๊ทธ๋ฃน๋‹น 176๋ช… (์ด 352๋ช…)
d = 0.5 (ํฐ ํšจ๊ณผ): ๊ทธ๋ฃน๋‹น 64๋ช… (์ด 128๋ช…)
d = 0.8 (๋งค์šฐ ํฐ ํšจ๊ณผ): ๊ทธ๋ฃน๋‹น 26๋ช… (์ด 51๋ช…)

12. ๊ฒ€์ • ์„ ํƒ ์š”์•ฝํ‘œ

๋ฐ์ดํ„ฐ ์œ ํ˜•๋ณ„ ๊ฒ€์ • ์„ ํƒ

์ƒํ™ฉ๋ชจ์ˆ˜์  ๊ฒ€์ •๋น„๋ชจ์ˆ˜์  ๊ฒ€์ •
1๊ฐœ ํ‘œ๋ณธ ํ‰๊ท  vs ๊ธฐ์ค€๊ฐ’One-sample t-testWilcoxon signed-rank
2๊ฐœ ๋…๋ฆฝ ํ‘œ๋ณธ ๋น„๊ตIndependent t-testMann-Whitney U
2๊ฐœ ๋Œ€์‘ ํ‘œ๋ณธ ๋น„๊ตPaired t-testWilcoxon signed-rank
3๊ฐœ+ ๋…๋ฆฝ ํ‘œ๋ณธ ๋น„๊ตOne-way ANOVAKruskal-Wallis H
2ร—2 ๋ฒ”์ฃผ (์†Œํ‘œ๋ณธ)-Fisherโ€™s exact
๋ฒ”์ฃผ ๋…๋ฆฝ์„ฑ-Chi-square
๋Œ€์‘ ๋ฒ”์ฃผ ์ „ํ›„ ๋น„๊ต-McNemarโ€™s
์ƒ๊ด€๊ด€๊ณ„Pearson rSpearman ฯ, Kendall ฯ„

์ƒํ™ฉ๋ณ„ ๋น ๋ฅธ ๊ฐ€์ด๋“œ

Q: ๋‘ ๊ทธ๋ฃน ํ‰๊ท  ๋น„๊ต? โ”œโ”€โ”€ ๊ฐ™์€ ๋Œ€์ƒ์˜ ์ „ํ›„? โ†’ ๋Œ€์‘ํ‘œ๋ณธ t-test (์ •๊ทœ) / Wilcoxon (๋น„์ •๊ทœ) โ””โ”€โ”€ ๋‹ค๋ฅธ ๋Œ€์ƒ? โ†’ ๋…๋ฆฝํ‘œ๋ณธ t-test (์ •๊ทœ) / Mann-Whitney (๋น„์ •๊ทœ) Q: 3๊ฐœ ์ด์ƒ ๊ทธ๋ฃน ๋น„๊ต? โ”œโ”€โ”€ ์ •๊ทœ๋ถ„ํฌ? โ†’ One-way ANOVA โ””โ”€โ”€ ๋น„์ •๊ทœ๋ถ„ํฌ? โ†’ Kruskal-Wallis Q: ๋‘ ๋ฒ”์ฃผํ˜• ๋ณ€์ˆ˜ ๊ด€๊ณ„? โ”œโ”€โ”€ ๊ธฐ๋Œ€๋นˆ๋„ < 5 ์žˆ์Œ? โ†’ Fisher's exact โ””โ”€โ”€ ๊ธฐ๋Œ€๋นˆ๋„ โ‰ฅ 5? โ†’ Chi-square Q: ๋‘ ์—ฐ์†ํ˜• ๋ณ€์ˆ˜ ๊ด€๊ณ„? โ”œโ”€โ”€ ์„ ํ˜• ๊ด€๊ณ„? โ†’ Pearson r โ””โ”€โ”€ ๋‹จ์กฐ ๊ด€๊ณ„? โ†’ Spearman ฯ

ํ€ด์ฆˆ

๋ฌธ์ œ 1

Titanic ๋ฐ์ดํ„ฐ์—์„œ ๊ฐ์‹ค ๋“ฑ๊ธ‰(pclass)์— ๋”ฐ๋ผ ์ƒ์กด์œจ์— ์œ ์˜ํ•œ ์ฐจ์ด๊ฐ€ ์žˆ๋Š”์ง€ ์ ์ ˆํ•œ ๊ฒ€์ •์„ ์ˆ˜ํ–‰ํ•˜์„ธ์š”.

์ •๋‹ต ๋ณด๊ธฐ

# ๋ฒ”์ฃผํ˜• vs ๋ฒ”์ฃผํ˜• โ†’ ์นด์ด์ œ๊ณฑ ๊ฒ€์ • contingency = pd.crosstab(titanic['pclass'], titanic['survived']) chi2, p_value, dof, expected = chi2_contingency(contingency) print("๊ต์ฐจํ‘œ:") print(contingency) print(f"\nฯ‡ยฒ = {chi2:.4f}, p-value = {p_value:.6f}") print(f"\n๊ฒฐ๋ก : {'๊ฐ์‹ค ๋“ฑ๊ธ‰๊ณผ ์ƒ์กด์œจ์€ ์—ฐ๊ด€๋จ' if p_value < 0.05 else '์—ฐ๊ด€ ์—†์Œ'}") # ํšจ๊ณผ ํฌ๊ธฐ v = cramers_v(contingency) print(f"Cramรฉr's V = {v:.4f} (์ค‘๊ฐ„ ์ •๋„์˜ ์—ฐ๊ด€)")

๋ฌธ์ œ 2

Tips ๋ฐ์ดํ„ฐ์—์„œ ํก์—ฐ์ž์™€ ๋น„ํก์—ฐ์ž์˜ ํŒ ๊ธˆ์•ก ๋ถ„ํฌ๊ฐ€ ๋‹ค๋ฅธ์ง€ ์ ์ ˆํ•œ ๊ฒ€์ •์œผ๋กœ ํ™•์ธํ•˜์„ธ์š”.

์ •๋‹ต ๋ณด๊ธฐ

smoker_tip = tips[tips['smoker'] == 'Yes']['tip'] nonsmoker_tip = tips[tips['smoker'] == 'No']['tip'] # ์ •๊ทœ์„ฑ ๊ฒ€์ • _, p_smoker = shapiro(smoker_tip) _, p_nonsmoker = shapiro(nonsmoker_tip) print(f"์ •๊ทœ์„ฑ (ํก์—ฐ): p = {p_smoker:.4f}") print(f"์ •๊ทœ์„ฑ (๋น„ํก์—ฐ): p = {p_nonsmoker:.4f}") # ์ •๊ทœ์„ฑ ๋ถˆ์ถฉ์กฑ โ†’ Mann-Whitney U ์‚ฌ์šฉ stat, p_value = mannwhitneyu(smoker_tip, nonsmoker_tip) print(f"\nMann-Whitney U: {stat:.2f}") print(f"p-value: {p_value:.4f}") print(f"\n๊ฒฐ๋ก : {'ํŒ ๋ถ„ํฌ๊ฐ€ ๋‹ค๋ฆ„' if p_value < 0.05 else 'ํŒ ๋ถ„ํฌ ์ฐจ์ด ์—†์Œ'}")

๋‹ค์Œ ๋‹จ๊ณ„

  • ํšŒ๊ท€๋ถ„์„์—์„œ ๋ณ€์ˆ˜ ๊ฐ„ ๊ด€๊ณ„๋ฅผ ๋ชจ๋ธ๋งํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์›Œ๋ณด์„ธ์š”.
  • A/B ํ…Œ์ŠคํŠธ์—์„œ ์‹คํ—˜ ์„ค๊ณ„๋ฅผ ๋ฐฐ์›Œ๋ณด์„ธ์š”.
Last updated on

๐Ÿค–AI Mock InterviewPractice with real questions