ANOVA 분석
[수업 목표]
- 데이터를 활용하여 여러 생산라인 간의 품질 차이를 통계적으로 분석하는 방법을 이해한다.
- 분산분석을 통해 귀무가설 검정 방법과 p-value 해석 방법을 익힌다.
- **ANOVA **및 사후검정(Tukey HSD)을 통해 구체적인 라인 간 차이를 분석하는 방법을 숙지한다.
- Python의 scipy, statsmodels 라이브러리를 활용하여 F-통계량과 p-value를 계산하고 결과를 해석하는 방법을 배운다.
📕
- **ANOVA **분석 개요
기본 개념을 짚어봅시다!
(1) 기본 개념 ANOVA (Analysis of Variance, 분산분석)는 📊 세 개 이상의 집단 평균 차이를 동시에 비교하는 통계 기법입니다. 집단 간 평균 차이를 분산 (Variance)을 이용해서 분석하는 거죠!
- 일원분산분석 (One-way ANOVA): 한 가지 독립변수 (요인)에 여러 수준이 존재하고, 종속변수가 연속형인 경우를 말합니다. **(2) 아노바 분석 사용 예시 **
- 🍎 서로 다른 세 종류의 비료 (A, B, C)를 사용했을 때, 사과의 평균 무게에 차이가 있는지 비교하고 싶을 때
- 📚 새로운 교육 프로그램 (A, B, C)의 효과를 비교하기 위해, 각 프로그램을 이수한 학생들의 평균 시험 점수를 비교할 때
- 한 제조업체에서 제품의 품질(예: 강도)이 3개의 다른 생산 라인에서 다를 가능성을 조사하려 할때, 생산 라인 A, B, C에서 샘플 데이터를 수집하여 품질 차이가 통계적으로 유의미한지 확인
📕
- 가정 (Assumptions)
모델 마다 기본 가정이 있습니다.
ANOVA는 다음과 같은 가정을 만족해야 신뢰할 수 있는 결과를 얻을 수 있습니다. 🤔
- 정규성 (Normality): 각 집단의 종속변수가 정규분포를 따른다고 가정합니다.
- 등분산성 (Homogeneity of variance): 각 집단의 분산이 동일하다고 가정합니다. (Bartlett test, Levene test 등으로 확인)
- 독립성 (Independence): 표본들이 서로 독립적이어야 합니다. (한 대상이 여러 집단에 중복 참여 X) ⚠️ 가정 위배 시: 정규성이나 등분산성 가정이 크게 위배된다면, Welch ANOVA (등분산성 미가정) 나 Kruskal-Wallis 검정 (비모수적 대안)을 고려할 수 있습니다.
📕 3. 수학적 배경
수학적으로 컨셉을 이해해 봅시다.
(1) 분산분석 (ANOVA)의 아이디어

ANOVA는 총 변동을 집단 간 변동과 집단 내 변동으로 나누어 분석합니다.
- 총제곱합 (SST): 전체 변동 (집단 간 변동 + 집단 내 변동)
- 집단 간 제곱합 (SSB): 집단별 평균 간의 차이로 인한 변동
- 집단 내 제곱합 (SSE): 각 집단 내에서 개별 데이터가 집단 평균과 얼마나 다른지 나타내는 변동 💡 SST = SSB + SSE
(2) F 통계량 분산분석의 핵심 지표는 F 통계량이며, 집단 간 변동과 집단 내 변동의 비율로 계산됩니다. 🔎 F = MSB / MSE
- MSB (Between Mean Square): SSB / (k - 1)
- MSE (Error Mean Square): SSE / (N - k)
- k: 집단 수
- N: 전체 표본 수 🎯 귀무가설 (): 모든 집단의 평균은 동일하다. 🎯 대립가설 (): 적어도 한 집단의 평균은 다르다. 💡 그룹 간 차이가 크면 MSB가 커져서 F 값이 커지고, 귀무가설을 기각 (집단 평균 차이 존재) 하게 됩니다.
좀 더 수치적으로 살펴 볼까요?
📕 실습
**1. ** 3개의 생산 라인(Machine A, Machine B, Machine C)이 생산 1회당 걸리는 시간(
production_time)에 차이가 있는지 확인
- 목표: 동일한 제품을 생산할 때,
- 생산 라인 A(Machine A)
- 생산 라인 B(Machine B)
- 생산 라인 C(Machine C) 이 세 가지 라인에서 평균 생산 시간에 차이가 있는지 알아보려 함.
- 데이터 구성: 총 10개의 생산 시점(ID)에서 “생산 1회당 걸린 시간(
production_time)”을 측정했고, 측정 시 어떤 라인을 사용했는지(그룹)를 기록하였음.
2. 데이터
다음 표는 실제로 측정된 예시 데이터입니다. (
production_time단위: 시간(Hours) 가정)
id production_time group (라인) group mean Between Within 1 5.3 A 6.000 0.194 0.490 2 6.0 A 6.000 0.194 0.000 3 6.7 A 6.000 0.194 0.490 4 5.5 B 5.950 0.240 0.203 5 6.2 B 5.950 0.240 0.063 6 6.4 B 5.950 0.240 0.203 7 5.7 B 5.950 0.240 0.063 8 7.5 C 7.533 1.195 0.001 9 7.2 C 7.533 1.195 0.111 10 7.9 C 7.533 1.195 0.134 group mean: 해당 라인(A, B, C)의 평균 생산 시간 Between: 각 라인의 평균이 전체평균에서 얼마나 떨어져 있는지를 나타내는 제곱 편차 분(집단간 분산 기여도) Within: 개별 관측치가 그 라인의 평균으로부터 얼마나 떨어져 있는지를 나타내는 제곱 편차 분(집단내 분산 기여도)
3. 전체평균(Grand Mean)과 그룹별 평균
- 전체 평균(Grand Mean): 모든
production_time의 평균- 그룹별 평균:
- 라인 A 평균: 6.00 시간
- 라인 B 평균: 5.95 시간
- 라인 C 평균: 7.53 시간 예시에서 전체평균은 약 6.44 시간(10개 생산 시점의 평균)이라 가정되어 있습니다.
4. 집단 간 변동(Between-Group Variance)
- *Between 변동(집단간 변동)**은 “각 그룹 평균이 전체평균에서 얼마나 떨어져 있는가?”를 바탕으로 계산합니다.
- 라인 A: (평균 6.00 - 전체평균 6.44)²
- 라인 B: (평균 5.95 - 전체평균 6.44)²
- 라인 C: (평균 7.53 - 전체평균 6.44)²
각 그룹의 표본 크기에 따라 가중합을 해줍니다.
실제 수치를 대입하면,
- 집단 간 자유도():
- 여기서 (A, B, C) → k=3 =3-1=2
5. 집단 내 변동(Within-Group Variance)
- *Within 변동(집단내 변동)**은 “개별 관측값이 자신이 속한 그룹평균과 얼마나 차이 나는지”로 구합니다.
예:
- 라인 A에 속한 id=1 (5.3) → (5.3 - 6.00)² = 0.49
- 라인 A에 속한 id=2 (6.0) → (6.0 - 6.00)² = 0.00
- …
- 라인 B, C도 같은 방식으로 합산 모든 관측치를 더한 결과, Within SS = 1.757
- 집단 내 자유도():n - k
- 전체 샘플 수 , 그룹 수 → n=10 k=3 =10−3=7
6. F 통계량
일원분산분석의 F 값은, “집단 간 분산”과 “집단 내 분산”의 비율로 정의됩니다.
- 집단 간 평균제곱 (MS Between)
- 집단 내 평균제곱 (MS Within)
- F-value
- 일반적으로 F 분포표(또는 소프트웨어 계산)를 통해, 주어진 자유도(df1=2, df2=7)에 대한 p값이 유의수준(0.05 등)보다 작다면, “라인 A, B, C 간에 평균 생산 시간에 유의미한 차이가 있다”고 결론 내릴 수 있습니다.
📕
- 절차
아노바 분석의 전체 흐름을 짚어 봅시다.
- 데이터 수집: 예) 3개 집단 (A, B, C), 각 집단별로 10명에게서 종속변수를 측정
- 가정 확인:
- 정규성 검정 (Shapiro-Wilk test, Kolmogorov-Smirnov test 등)
- 등분산성 검정 (Levene’s test, Bartlett’s test)
- ANOVA 수행: 분산분석 표 (ANOVA table) 에서 F 통계량과 p-값 도출
- 결과 해석: p < 0.05 일 경우, “적어도 한 집단의 평균이 다른 집단과 유의한 차이”가 있다고 판단
- 사후검정 (Post-hoc test): 집단이 3개 이상이면, 유의미한 차이가 나는 “특정 집단 간” 쌍별 비교를 수행 (Tukey HSD, Scheffé, Bonferroni 등)
📕
- 사후 검정 (Post-hoc tests)
아노바 분석의 전체 흐름을 짚어 봅시다.
(1) 주요 기법
- Tukey HSD (Test): 등분산 가정이 충족되고, 표본 크기도 비슷한 경우 자주 사용됩니다. 직관적이고 쉬운 해석이 가능해요! 😊
- Bonferroni: 쌍별 t-검정에 대한 유의수준 보정을 적용합니다. 보수적인 방법이에요. 🧐
- Scheffé: 보수적인 방법으로, 표본 크기가 다르거나 가정이 조금 깨져도 적용 가능합니다. 👍 위 방법 이상 깊게 가는걸 권장 드리지않습니다. 통계적 깊은 연구가 아니면, 다른 모델을 사용하는 것을 권장드립니다.
(2) 사후검정 결과 해석 어떤 두 집단 간 평균 차이가 p < 0.05 로 유의하다면, 그 두 집단 사이에 통계적으로 의미 있는 차이가 있다고 결론 내립니다. 모든 쌍별 비교 결과를 표로 정리하는 경우가 많아요. 📊
📕
- Python 예시 코드 (One-way ANOVA)
위 과정을 코드로 살펴 봅시다.
import numpy as np
import pandas as pd
from scipy.stats import f_oneway
# statsmodels 패키지로 ANOVA & Post-hoc
import statsmodels.api as sm
from statsmodels.formula.api import ols
from statsmodels.stats.multicomp import pairwise_tukeyhsd
# ------------------------------------------------
# 1) 예시 데이터 생성
# ------------------------------------------------
np.random.seed(42)
group_A = np.random.normal(loc=50, scale=5, size=30) # A 집단
group_B = np.random.normal(loc=55, scale=5, size=30) # B 집단
group_C = np.random.normal(loc=60, scale=5, size=30) # C 집단
df = pd.DataFrame({
'score': np.concatenate([group_A, group_B, group_C]),
'group': ['A']*30 + ['B']*30 + ['C']*30
})
# ------------------------------------------------
# 2) SciPy를 이용한 간단 ANOVA
# ------------------------------------------------
f_stat, p_val = f_oneway(group_A, group_B, group_C)
print("== One-way ANOVA (SciPy) ==")
print(f"F-statistic = {f_stat:.4f}, p-value = {p_val:.4f}\n")
# ------------------------------------------------
# 3) StatsModels를 이용한 ANOVA
# ------------------------------------------------
model = ols('score ~ C(group)', data=df).fit()
anova_table = sm.stats.anova_lm(model, typ=2)
print("== ANOVA Table (StatsModels) ==")
print(anova_table)
# ------------------------------------------------
# 4) 사후검정 (Tukey HSD)
# ------------------------------------------------
tukey_result = pairwise_tukeyhsd(endog=df['score'],
groups=df['group'],
alpha=0.05)
print("\n== Tukey Post-hoc Test ==")
print(tukey_result)
# 요약 해석
# - ANOVA 결과 p < 0.05라면, 세 집단 간 평균에 통계적 유의 차이가 있음.
# - Tukey 결과를 보면, 어떤 집단 간 차이가 유의한지(pairwise) 표시됨.
📕
- Tukey HSD 검정이란 무엇일까요?
분산 분석 (ANOVA) 의 사후 분석 (Post-hoc test) 방법 중 하나!
분산 분석 (ANOVA) 의 사후 분석 (Post-hoc test) 방법으로, ANOVA 에서 여러 그룹 간 평균 차이가 유의미하다고 나왔을 때, 어떤 그룹 간에 차이가 있는지 구체적으로 확인하는 데 사용됩니다. 🔎
Tukey HSD 의 주요 특징
- 다중 비교 문제 해결: ANOVA 는 여러 그룹 간 평균 차이가 있는지 여부만 알려주지만, Tukey HSD 는 모든 가능한 그룹 쌍을 비교하면서 다중 비교로 인한 오류를 제어합니다.
- 균등한 표본 크기 및 분산 가정: Tukey HSD 는 각 그룹의 분산이 동일하고 (등분산성), 표본 크기가 비슷할 때 더욱 신뢰할 수 있는 결과를 제공합니다.
- 유의수준 조정: 다중 비교에 맞게 유의수준 (α) 을 조정하여 신뢰도를 높입니다.
Tukey HSD 의 공식
📕
- Tukey HSD 검정 절차
실제 절차를 한번 살펴볼까요?!
- ANOVA 수행: 먼저 ANOVA 를 수행하여 그룹 간 평균 차이가 유의미한지 확인합니다.
- H0: 모든 그룹 간 평균이 동일하다 (μ1=μ2=μ3=…).
- H1: 적어도 하나의 그룹이 다른 그룹과 평균이 다르다.
- 유의미한 결과 확인: ANOVA 결과 p<α 인 경우, 사후 분석 (Tukey HSD) 을 수행합니다.
- Tukey HSD 계산: 각 그룹 간 평균 차이를 계산하고, 유의수준에 따라 통계적 유의미성을 판정합니다.
- 결과 해석: 유의미한 그룹 쌍을 확인하여 어떤 그룹 간에 차이가 존재하는지 명시합니다.
📕
- Python 코드 예제
위 과정을 코드로 살펴 봅시다.
한 제조업체에서 세 가지 공정 (A, B, C) 이 제품 품질 (강도) 에 미치는 영향을 분석합니다.
import pandas as pd
from statsmodels.stats.multicomp import pairwise_tukeyhsd
from statsmodels.formula.api import ols
import statsmodels.api as sm
# 데이터 생성
data = pd.DataFrame({
"공정": ["A", "A", "A", "B", "B", "B", "C", "C", "C"],
"강도": [85, 87, 86, 88, 90, 89, 92, 91, 93]
})
# 1. ANOVA 수행
model = ols('강도 ~ 공정', data=data).fit()
anova_table = sm.stats.anova_lm(model, typ=2)
print("ANOVA 결과:\n", anova_table)
# 2. Tukey HSD 수행
tukey = pairwise_tukeyhsd(endog=data["강도"], groups=data["공정"], alpha=0.05)
print("\nTukey HSD 결과:\n", tukey)
(출력 결과)
ANOVA 결과:
sum_sq df F PR(>F). Residual
공정 40.6667 2 48.0000 0.00034 5.0833 6p<0.05 이므로, 공정 A, B, C 중 적어도 하나의 평균이 다릅니다.
- Tukey HSD 결과:
Multiple Comparison of Means - Tukey HSD, FWER=0.05
==============================================
group1 group2 meandiff p-adj lower upper reject
----------------------------------------------------
A B 3.0 0.001 1.748 4.252 True
A C 6.0 0.001 4.748 7.252 True
B C 3.0 0.001 1.748 4.252 True
----------------------------------------------------📕
- 분석 결과 작성 시 팁
최종적으로 아래 내용을 잘 설명해주면 됩니다.
- 기본 통계치: 각 집단의 평균, 표준편차, 표본 크기 제시
- ANOVA 표: F 값, 자유도 (df), p-값, 효과크기 () 등
- 사후검정: 어떤 집단 간 차이가 유의미한지 명시
- 가정 충족 여부: 정규성, 등분산성 검정 결과 간단히 언급
- 시각화: 박스플롯, 에러바 플롯 등을 통해 집단 간 평균/분포 차이를 시각적으로 표현
📕
- 요약
최종 요약 정리
- 일원분산분석 (One-way ANOVA) 은 세 개 이상의 독립 집단 간 종속변수의 평균 차이를 검정하는 대표적인 방법입니다.
- 전제되는 정규성, 등분산성, 독립성 가정을 만족해야 신뢰도 높은 결과를 얻을 수 있습니다.
- 결과가 유의하다면, 사후검정을 통해 구체적으로 어느 집단 사이에 차이가 있는지 파악해야 합니다.
- Python 에서는
scipy.stats.f_oneway나statsmodels의anova_lm을 통해 손쉽게 ANOVA 를 수행하고,pairwise_tukeyhsd함수로 Tukey 사후검정을 진행할 수 있습니다.