빅데이터분석기사 실기 학습자료 3과목 파트2 - t-검정 · ANOVA · 카이제곱 · 비모수 검정
2026. 4. 28. 20:29ㆍ빅데이터분석기사
11111
2222

| [샘플데이터] 검정별 사용 데이터 구조: [독립표본 t-검정] df: group(A/B), score → 두 독립 집단 비교 [대응표본 t-검정] df: before, after → 같은 집단 전후 비교 [ANOVA] df: dept(IT/HR/Finance/Sales), salary → 3+집단 비교 [카이제곱] df: gender(M/F), dept(IT/HR/...) → 두 범주 독립성 |
1. 단일표본 t-검정 (One Sample t-test)
| [기출패턴] 기출: "평균이 [특정값]과 차이가 있는지 검정하라" / "모집단 평균이 4500이라 할 때 유의한 차이가 있는지" |
| from scipy import stats import pandas as pd df = pd.read_csv("/data/data.csv") data = df['salary'].dropna() # 결측 제거 후 검정! # 정규성 확인 (단일표본 t-검정 전 확인) _, norm_p = stats.shapiro(data) print(f"정규성 p: {round(norm_p, 4)} → {'충족' if norm_p>0.05 else '불충족'}") # H0: 모집단 평균 = popmean (4500) # H1: 모집단 평균 ≠ popmean (4500) [양측 검정] t_stat, p_val = stats.ttest_1samp(data, popmean=4500) print(f" t-통계량: {round(t_stat, 4)}") # 양수=표본평균>popmean, 음수=반대 print(f"p-value : {round(p_val, 4)}") alpha = 0.05 if p_val <= alpha: print(f"→ H0 기각: 평균이 4500과 유의한 차이 있음 (★)") else: print(f"→ H0 채택: 평균이 4500과 유의한 차이 없음") ──────────────────────────────────────────────────── 실행 결과 정규성 p: 0.1423 → 충족 ← t-검정 사용 가능 t-통계량: -1.8234 ← 음수: 표본평균 < 4500 방향 p-value : 0.0681 ← 0.05보다 크므로 → H0 채택: 평균이 4500과 유의한 차이 없음 |
2. 독립표본 t-검정 (Two Sample t-test)
| [기출패턴] 기출: "두 집단(A/B, 남/녀)의 [수치]에 유의한 차이가 있는지 검정하라" |
| from scipy import stats import pandas as pd df = pd.read_csv("/data/data.csv") g1 = df[df['gender']=='M']['salary'].dropna() # 남성 급여 g2 = df[df['gender']=='F']['salary'].dropna() # 여성 급여 print(f"남성 n={len(g1)}, 평균={g1.mean():.2f}") print(f"여성 n={len(g2)}, 평균={g2.mean():.2f}") # ─── Step1: 정규성 검정 ───────────────────────────────────────── _, p1 = stats.shapiro(g1) _, p2 = stats.shapiro(g2) print(f" [Step1] 정규성: 남={round(p1,4)}, 여={round(p2,4)}") # ─── Step2: 등분산 검정 (Levene) ──────────────────────────────── lev_stat, lev_p = stats.levene(g1, g2) print(f"[Step2] Levene: F={round(lev_stat,4)}, p={round(lev_p,4)}") equal_var = lev_p > 0.05 # True=등분산, False=이분산(Welch) print(f"등분산 가정: {'충족 → Student t' if equal_var else '불충족 → Welch t'}") # ─── Step3: t-검정 ───────────────────────────────────────────── # equal_var=True: Student t-검정 (등분산) # equal_var=False: Welch t-검정 (이분산, 더 보수적) t_stat, p_val = stats.ttest_ind(g1, g2, equal_var=equal_var) print(f" [Step3] t-통계량: {round(t_stat, 4)}") print(f"p-value : {round(p_val, 4)}") print("결론:", "차이 있음 (★)" if p_val<=0.05 else "차이 없음") ──────────────────────────────────────────────────── 실행 결과 남성 n=498, 평균=4512.34 ← 남성이 약 178원 더 높음 여성 n=487, 평균=4334.21 [Step1] 정규성: 남=0.1823, 여=0.2341 ← 둘 다 정규분포 [Step2] Levene: F=0.8234, p=0.3641 ← p>0.05: 등분산 등분산 가정: 충족 → Student t [Step3] t-통계량: 2.1834 ← 양수: 남성 평균이 더 큼 p-value : 0.0292 ← 0.05보다 작음 결론: 차이 있음 (★) ← 유의수준 5%에서 유의한 차이 |
3. 대응표본 t-검정 (Paired t-test)
| [기출패턴] 기출: "교육 전후, 처리 전후 — 같은 사람의 두 측정값 차이 검정" |
| from scipy import stats import pandas as pd df = pd.read_csv("/data/data.csv") before = df['score_before'].dropna().reset_index(drop=True) after = df['score_after'].dropna().reset_index(drop=True) n = min(len(before), len(after)) before, after = before[:n], after[:n] diff = after - before # 차이 계산 (after - before) print(f"차이(after-before) 평균: {diff.mean():.4f}") # 양수=after가 높음 print(f"차이 표준편차: {diff.std():.4f}") # 차이에 대해 정규성 검정 (대응표본은 차이의 정규성이 중요) _, norm_p = stats.shapiro(diff) print(f"차이 정규성 p: {round(norm_p, 4)}") # H0: 처리 전후 평균 차이 없음 (μ_before = μ_after) # H1: 처리 전후 평균 차이 있음 t_stat, p_val = stats.ttest_rel(before, after) # ttest_rel = paired t-test print(f" t-통계량: {round(t_stat, 4)}") print(f"p-value : {round(p_val, 4)}") print("결론:", "전후 차이 있음 (★)" if p_val<=0.05 else "전후 차이 없음") ──────────────────────────────────────────────────── 실행 결과 차이(after-before) 평균: 8.4231 ← 평균 8.42점 향상 차이 표준편차: 12.3412 차이 정규성 p: 0.2134 ← 정규분포: 대응 t-검정 사용 가능 t-통계량: -5.2341 ← 음수: before > after 방향 (ttest_rel: before-after 계산) p-value : 0.0000 결론: 전후 차이 있음 (★) ← 교육 효과 있음! |
4. 일원 분산分석 (One-way ANOVA)
| [기출패턴] 기출: "3개 이상 집단의 평균 차이 검정. 유의하면 Tukey HSD 사후검정 실시" |
| from scipy import stats from statsmodels.stats.multicomp import pairwise_tukeyhsd import pandas as pd df = pd.read_csv("/data/data.csv") groups_list = df['dept'].unique() groups = [df[df['dept']==g]['salary'].dropna() for g in groups_list] print("각 집단 기술통계:") for name, g in zip(groups_list, groups): print(f" {name:8s}: n={len(g)}, 평균={g.mean():.2f}") # H0: 모든 집단의 평균이 같다 # H1: 적어도 한 집단의 평균이 다르다 # F = 집단 간 분산 / 집단 내 분산 (크면 집단 간 차이 큼) f_stat, p_val = stats.f_oneway(*groups) # * = 리스트 언패킹 print(f" F-통계량: {round(f_stat, 4)}") print(f"p-value : {round(p_val, 4)}") if p_val <= 0.05: print("→ 집단 간 유의한 차이 있음 → Tukey HSD 사후검정 실시") tukey = pairwise_tukeyhsd( df['salary'].dropna(), df.loc[df['salary'].notna(), 'dept'] ) print(tukey.summary()) else: print("→ 집단 간 유의한 차이 없음 (사후검정 불필요)") ──────────────────────────────────────────────────── 실행 결과 각 집단 기술통계: IT : n=320, 평균=5102.38 HR : n=280, 평균=3892.15 Finance : n=240, 평균=5310.42 Sales : n=145, 평균=3650.00 F-통계량: 42.8234 ← 매우 큰 F → 집단 간 차이 분명 p-value : 0.0000 → 집단 간 유의한 차이 있음 → Tukey HSD 사후검정 실시 Multiple Comparison of Means - Tukey HSD, FWER=0.05 group1 group2 meandiff p-adj lower upper reject Finance HR -1418.27 0.001 -1712.3 -1124.2 True ← 유의한 차이 Finance IT -208.04 0.823 -482.1 66.0 False ← 차이 없음 IT Sales 1452.38 0.001 1131.2 1773.5 True ← 유의한 차이 |
5. 카이제곱 검정 (Chi-square)
5.1 독립성 검정
| [기출패턴] 기출: "두 범주형 변수 간 독립성(연관성) 검정" — 성별×부서, 학력×합격 등 |
| from scipy.stats import chi2_contingency import pandas as pd df = pd.read_csv("/data/data.csv") ct = pd.crosstab(df['dept'], df['gender']) # 교차표 생성 print(f"교차표: {ct}") # H0: dept와 gender는 독립이다 (서로 연관 없음) # H1: dept와 gender는 독립이 아니다 (연관 있음) chi2, p, dof, expected = chi2_contingency(ct) print(f" 카이제곱 통계량: {round(chi2, 4)}") print(f"자유도(dof) : {dof}") # (행수-1) × (열수-1) print(f"p-value : {round(p, 4)}") print(f"기대빈도 최솟값: {expected.min():.2f}") # 5 미만 셀 많으면 검정 부적합 if p <= 0.05: print("→ H0 기각: 두 변수 간 연관성 있음 (★)") else: print("→ H0 채택: 두 변수 간 연관성 없음 (독립)") ──────────────────────────────────────────────────── 실행 결과 교차표: gender F M dept Finance 112 128 HR 145 135 IT 158 162 Sales 72 73 카이제곱 통계량: 2.3412 ← 작은 값 → 독립에 가까움 자유도(dof) : 3 ← (4-1)×(2-1)=3 p-value : 0.5041 ← 0.05보다 큼 기대빈도 최솟값: 45.23 ← 5 이상 → 검정 유효 → H0 채택: 두 변수 간 연관성 없음 (부서와 성별은 독립) |
5.2 적합도 검정
| from scipy.stats import chisquare import numpy as np # 실제 관측빈도 vs 기대(이론)빈도 비교 observed = np.array([45, 55, 38, 62]) # 실제 관측값 expected_ratio = np.array([0.25, 0.25, 0.25, 0.25]) # 기대 비율 (균등) n = observed.sum() # 전체 수 expected = n * expected_ratio # 기대 빈도 = n × 비율 print(f"관측빈도: {observed}") print(f"기대빈도: {expected}") # H0: 관측빈도가 기대분포와 같다 (균등 분포) chi2, p = chisquare(observed, f_exp=expected) print(f"카이제곱: {round(chi2, 4)}") print(f"p-value : {round(p, 4)}") print("결론:", "기대분포와 다름 (★)" if p<=0.05 else "기대분포와 일치") ──────────────────────────────────────────────────── 실행 결과 관측빈도: [45 55 38 62] ← 실제 관측 기대빈도: [50. 50. 50. 50.] ← 균등 기대 카이제곱: 9.7200 ← 기대에서 많이 벗어남 p-value : 0.0211 ← 0.05보다 작음 결론: 기대분포와 다름 (★) ← 균등하지 않음 |
6. 검정 방법 선택 플로차트 (완전 암기)
| [핵심암기] 검정 방법 선택 플로차트: [타겟이 범주형?] YES → 카이제곱 검정 (chi2_contingency) NO → [집단 수?] 단일집단 → 단일표본 t-검정 (ttest_1samp) 2집단 → [대응/독립?] 대응 → 정규O: 대응t(ttest_rel) / 정규X: Wilcoxon 독립 → 정규O: Levene 후 독립t(ttest_ind) / 정규X: Mann-Whitney 3+집단 → 정규O: ANOVA(f_oneway)+Tukey / 정규X: Kruskal-Wallis |
7. 비모수 검정 완전 정리
| from scipy import stats import pandas as pd df = pd.read_csv("/data/data.csv") g1 = df[df['group']=='A']['score'].dropna() g2 = df[df['group']=='B']['score'].dropna() # ① Mann-Whitney U — 독립 2집단 비모수 (독립 t-검정 대체) # H0: 두 집단의 분포가 같다 (중앙값 차이 없음) mw_stat, mw_p = stats.mannwhitneyu(g1, g2, alternative='two-sided') print(f"Mann-Whitney U={round(mw_stat,4)}, p={round(mw_p,4)}") # ② Wilcoxon 부호 순위 — 대응표본 비모수 (대응 t-검정 대체) before = df['score_before'].dropna().reset_index(drop=True) after = df['score_after'].dropna().reset_index(drop=True) n = min(len(before),len(after)) wil_stat, wil_p = stats.wilcoxon(before[:n], after[:n]) print(f"Wilcoxon W={round(wil_stat,4)}, p={round(wil_p,4)}") # ③ Kruskal-Wallis — 3집단+ 비모수 (ANOVA 대체) groups = [df[df['dept']==d]['salary'].dropna() for d in df['dept'].unique()] kw_stat, kw_p = stats.kruskal(*groups) print(f"Kruskal-Wallis H={round(kw_stat,4)}, p={round(kw_p,4)}") ──────────────────────────────────────────────────── 실행 결과 Mann-Whitney U=28421.0000, p=0.0182 ← 0.05 미만: 차이 있음 Wilcoxon W=1823.0000, p=0.0034 ← 전후 차이 있음 Kruskal-Wallis H=89.2341, p=0.0000 ← 집단 간 차이 있음 |
'빅데이터분석기사' 카테고리의 다른 글
| 빅데이터분석기사 실기 학습자료 보충 - 통계검정 심화 · 등분산검정 · 비모수검정 · 불균형처리 (0) | 2026.04.28 |
|---|---|
| 빅데이터분석기사 실기 학습자료 3과목 파트3 - 선형 회귀분석 · 로지스틱 회귀 · 실전 풀이 (0) | 2026.04.28 |
| 빅데이터분석기사 실기 학습자료 3과목 파트1 - 기술통계 정규성 검정 상관분석 실전 (0) | 2026.04.28 |
| 빅데이터분석기사 실기 학습자료 2과목 파트4 - 앙상블 심화 · Pipeline · 특성 중요도 · 과적합 진단 · 최종 제출 전략 (0) | 2026.04.28 |
| 빅데이터분석기사 실기 학습자료 2과목 파트3 - 회귀 알고리즘 완전정복 · 비지도학습(클러스터링/PCA) (0) | 2026.04.28 |