library(tidyverse)
library(showtext)
font_add_google("Nanum Gothic", "nanumgothic")
showtext_auto()
31 분산 분석의 기초: 제곱합(sum of squares)을 중심으로
(book?){lazic2016experimental, 이 장에서는 분산 분석(ANOVA)에서 제곱합(sum of squares)에 대해 설명한다. 제곱합은 분산 분석에서 매우 중요한 개념이다. 다음은 (Lazic 2016) 책에서 인용한 예이다.
간단한 데이터셋을 만들어 보자. x
라는 팩터 변수가 있고, y
라는 결과 변수(종속 변수)가 있다.
# A tibble: 8 × 2
y x
<dbl> <fct>
1 6 A
2 2 A
3 3 A
4 1 A
5 4 B
6 8 B
7 7 B
8 9 B
31.1 전체 제곱합(total sum of squares)
값들의 변동(variation)을 보기 위해서, 모든 관측치에 대해 전체 평균까지의 거리를 계산한 그래프를 그려보자.
df <- df %>%
mutate(id = row_number())
df
# A tibble: 8 × 3
y x id
<dbl> <fct> <int>
1 6 A 1
2 2 A 2
3 3 A 3
4 1 A 4
5 4 B 5
6 8 B 6
7 7 B 7
8 9 B 8
ggplot(df, aes(id, y)) +
geom_point() +
geom_hline(yintercept = mean(y), color = "red") +
geom_segment(aes(x = id, xend = id, y = y, yend = mean(y)), color = "steelblue") +
scale_x_continuous(breaks = 1:8, labels = x) +
labs(
x = "group x",
title = "각 관측치에서 평균까지의 거리"
) +
theme_minimal()
그래프에서 평균까지의 거리는 파란색 선으로 표시했다. 수식으로 표현하면 다음과 같다. \[ y_i - \bar{y} \]
이 값을 통계에서는 편차(deviation)라고 부른다. 편차는 관측치와 평균의 차이를 의미한다. 이런 편차의 합은 항상 0
이 된다.
통계학에서는 이 값을 사용하기 위해서 제곱을 취한다. 대표적인 경우가 분산(variance)이다. 분산은 편차의 제곱을 평균한 값이다. 수식으로 보면 다음과 같다.
분산은 다음과 같이 계산한다.
\[ \frac{1}{n-1} \sum_{i=1}^n (y_i - \bar{y})^2 \]
var()
함수를 사용하면 분산을 바로 계산할 수 있다.
var(df$y)
[1] 8.571429
여기서 우리는 제곱합(sum of squares)을 알아 보려고 한다. 제곱합은 편차의 제곱을 모두 더한 값이다. 수식으로 표현하면 다음과 같은데 분산과 다른 점은 뭔가로 나누지 않았다는 점이다. 위 그래프에서 파란색 선의 길이를 제곱하여 더하면 제곱합이 된다.
\[ \sum_{i=1}^n (y_i - \bar{y})^2 \]
sum(dev_y_squared)
[1] 60
31.2 그룹별 평균을 고려한 제곱합(Residual Sum of Squares)
위 그래프는 x
요인을 고려하지 않고, 전체 그룹에서의 데이터의 변동을 보여주고 있다. 이제 그룹별로 데이터의 변동을 보기 위해서 그룹별로 평균을 계산하고, 평균까지의 거리를 계산해 보자.
# A tibble: 8 × 4
# Groups: x [2]
y x id mean_y
<dbl> <fct> <int> <dbl>
1 6 A 1 3
2 2 A 2 3
3 3 A 3 3
4 1 A 4 3
5 4 B 5 7
6 8 B 6 7
7 7 B 7 7
8 9 B 8 7
그룹의 평균에 대해서 각 관측치까지의 거리를 그려보자.
ggplot(ddf, aes(id, y)) +
geom_point() +
geom_segment(aes(x = id, xend = id, y = y, yend = mean_y), color = "steelblue") +
annotate("segment", x = 1, xend = 4, y = 3, yend = 3, color = "red") +
annotate("segment", x = 5, xend = 8, y = 7, yend = 7, color = "orange") +
scale_x_continuous(breaks = 1:8, labels = x) +
labs(x = "group x", title = "각 관측치에서 평균까지의 거리") +
theme_minimal()
그룰별 평균까지의 거리를 제곱한 다음, 그 값들을 모두 더하면 잔차 제곱합(residual sum of squares)이 된다. 이 의미는 그룹별 평균을 고려한 후에도 남아있는 데이터의 변동을 의미한다.
부연하면, 상상해 보자. 그룹 A의 y
값이 모두 3
이고 그룹 B의 y
값이 모두 7
이라고 하자. 그러면 그룹별 평균을 고려한 후에는 남아있는 데이터의 변동은 없을 것이다(모두 빨간 평균 선에 놓일 것이다). 즉, 잔차 제곱합은 0이 된다.
31.3 그룹별 제곱합(sum of squares for each group)
전체 제곱합은 60
이었고, 그룹을 고려한 잔차 제곱합은 28
이었다. 그 차이를 그룹별 제곱합(sum of squares for each group)이라고 한다.
그래서 일반적으로 다음과 같은 관계를 가진다.
\[ \text{Total Sum of Squares} = \text{Residual Sum of Squares} + \text{Sum of Squares for each group} \]
다음과 같이도 표현할 수 있다. 즉, 그룹별 제곱합은 예측 변수의 효과를 반영한다. 잔차 제곱합은 예측 변수의 효과를 반영하지 못한 부분을 의미한다.
\[ \text{Total} = \text{Predictor(s)} + \text{Residual} \]
31.4 전체 데이터 변동에 기여하는 정도
다음과 같은 공식을 염두에 두면서 전체 데이터 변동성에 각 요소가 얼마 만큼 기여하는지 생각해 보자. \[ \text{Total} = \text{Predictor(s)} + \text{Residual} \]
그림 31.3은 생각하기 편하게 만든 간단한 그림이다.
실험1에서는 잔차보다 그룹별 제곱합이 더 큰 기여를 하고 있다. 실험2에서는 잔차보다 그룹별 제곱합이 더 작은 기여를 하고 있다. 이 기여도를 비율로 표현하고 싶다.
그런데 우리가 어떤 것을 서로 비교하고 싶다면 그것들의 단위를 맞출 필요가 있다. 이 경우에는 각 제곱합에서 자유도(degrees of freedom)를 나누어 주어야 한다. 그 나눈 값을 평균 제곱합(mean sum of squares)이라고 한다.
\[ \text{Mean Sum of Squares} = \frac{\text{Sum of Squares}}{\text{Degrees of Freedom}} \]
그래서 그룹별 평균 제곱합과 잔차 평균 제곱합의 비율을 가지고 데이터 변동성에 대한 기여도를 평가한다. 그것이 F-통계량(F-statistic)이다.
\[ F = \frac{\text{Mean Sum of Squares for each group}}{\text{Mean Sum of Squares for residual}} \]
F-통계량은 그룹별 평균 제곱합과 잔차 평균 제곱합의 비율을 가지고 데이터 변동성에 대한 기여도를 평가한다. 그리고 F-통계량은 항상 두 개의 자유도를 가지고 계산하게 된다.
31.5 R 함수: aov()
aov()
함수를 사용하면 분산 분석을 할 수 있다. 다음과 같이 사용하면 된다.
Df Sum Sq Mean Sq F value Pr(>F)
x 1 32 32.00 6.857 0.0397 *
Residuals 6 28 4.67
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
자유도 df1 =1
, df2 = 6
인 F-분포 곡선을 그려보자. 그리고 우리 데이터셋의 F-통계량인 6.86
을 표시해 보자. 해당 경계를 시작으로 오른쪽 Area Under the Curve(AUC)를 계산하면 p-값이 된다.
x <- seq(0, 10, length.out = 100)
y <- df(x, df1 = 1, df2 = 6)
ggplot(data.frame(x, y), aes(x, y)) +
geom_line() +
labs(x = "F-value", y = "Density") +
geom_vline(xintercept = 6.86, color = "red", linetype = "dashed") +
theme_minimal()
F-분포는 pf()
함수를 사용하여 p-값을 계산할 수 있다.
pf(6.86, df1 = 1, df = 6, lower.tail = FALSE)
[1] 0.0396308
31.6 정리
이 장에서는 분산 분석에서 중요하게 다뤄지는 제곱합(sum of squares) 등의 개념을 설명했다. 이 개념들과 그 전개 논리를 이해하면 분산 분석에 대해 잘 이해할 수 있을 것이다. 다음 장에서는 분산 분석을 실제로 해보자.
- 전체 제곱합(total sum of squares)
- 그룹별 제곱합(sum of squares for each group)
- 잔차 제곱합(residual sum of squares)
- 평균 제곱합(mean sum of squares)
- F-통계량(F-statistic)
- 분산 분석(ANOVA)