Programs/R

[R_tidyverse] 분산분석 ANOVA: 이원분산분석 Two-way ANOVA

도마도다 2024. 2. 29. 15:45

 

 

 

 분산분석 ANOVA

  • 통계분석의 종류는 목적에 따라 크게 (그룹 간) 차이검정, (변수 간) 관계검정으로 나눌 수 있음. 이 중 그룹 간 차이를 검정하는 방법으로는 t-검정과 분산분석(ANOVA)이 있는데, t-검정은 그룹이 1~2개일 때 사용되며, ANOVA는 그룹이 3개 이상일 때 사용함.
  • 분산분석은 이름에서 알 수 있듯이 데이터의 분산, 즉 데이터가 얼마나 퍼져있는지를 분석하는 방법임. 이를 통해 여러 그룹 간의 평균이 통계적으로 유의미하게 차이가 있는지를 판단함.
  • 분산분석의 주요 가정은 정규성, 독립성, 등분산성임. 정규성은 각 그룹의 데이터가 정규분포를 따르는지, 독립성은 각 그룹의 데이터가 서로 독립적인지, 등분산성은 각 그룹의 데이터가 동일한 분산을 가지는지를 가정함.
 
  • 분산분석의 종류
종류 특징
일원분산분석 
One-way ANOVA
1개의 독립변수가 있는 경우, 독립변수의 각 수준(그룹)간의 평균 차이를 검정
반복측정분산분석
Repeated Measures ANOVA
1개의 독립변수와 반복 측정된 종속변수가 있는 경우, 독립변수의 각 수준(그룹)간의 평균 차이와 시간에 따른 변화를 검정
이원분산분석 
Two-way ANOVA
2개의 독립변수가 있는 경우, 독립변수들의 각 수준(그룹)간의 평균 차이를 검정하며, 또한 독립변수들 간의 상호작용 효과를 검정
이원반복측정분산분석
Two-way Repeated Measures ANOVA
2개의 독립변수와 반복 측정된 종속변수가 있는 경우, 독립변수들의 각 수준(그룹)간의 평균 차이, 두 독립변수의 상호작용 효과, 그리고 시간에 따른 변화를 검정

 


 
 
 
 
 
 
 

 

이원분산분석 Two-way ANOVA 실습

*tidyverse 패키지를 활용한 분석방법
 
그룹을 구분하는 변수(요인)가 두  가지 일때 이원분산분석을 활용한다 
 
두 가지 요인의 interaction effect를 보고 싶을 때 활용할 수 있다.

 
오늘의 실습에서는 치킨을 만들 때 온도(200도/ 300도)와 방법(오븐/ 기름)에 따른 맛의 점수의 차이를 살펴본다.
온도 그리고 방법이라는 두 가지 변수가 있기 때문에 이원분산분석을 활용한다.

주요 질문: 온도와 시간이 맛을 결정하는데 중요한 요인인지? 두가지 요인들 간 상호작용효과가 있는지? 

귀무가설: 튀기는 온도와 방법 간에는 상호작용이 없다.
 
 

 

 

 

 

 

 

 차례

<차례>
  1. 패키지 설치 및 불러오기
  2. 데이터 불러오기, 기술통계, 그래프그리기
  3. 이상치 제거
  4. 샤피로 테스트: 정규분포 검정
  5. 등분산검정 
  6. 통계분석: ANOVA
  7. 사후검정: 다중비교
  8. 부록: 상호작용이 없을 경우
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 

1. 패키지 설치 및 불러오기

 
오늘의 실습을 위해 필요한 R 패키지. 패키지는 한 번 설치하면 다음에 다시 설치할 필요 없음. 
 
그러나 라이브러리는 매번 불러와야 함!
# 패키지 설치
install.packages("tidyverse") #쌍따옴표 주의
install.packages("tidymodels")
install.packages("rstatix")
install.packages("rskim")

#설치한 패키지 불러오기 (라이브러리)
library(tidyverse) #쌍따옴표 없음
library(tidymodels)
library(rstatix)
library(rskim)
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 

2. 데이터 불러오기, 기술통계, 그래프 그리기

# 데이터 불러오기
twa_tb <- read_csv("10.twa.csv",
                   col_names = TRUE,
                   na = ".",
                   locale = locale("ko", encoding = "euc-kr")) %>%
  mutate_if(is.character,as.factor) %>%
  mutate(방법 = factor(방법,
                         levels = c(1,2),
                         labels = c("오븐", "기름"))) %>%
  mutate(온도 = factor(온도,
                         levels = c(1,2),
                         labels = c("200도", "300도")))
 
# 데이터의 구조 파악
str(twa_tb)
twa_tb

# 기술통계(그룹 쪼개기)
skim(twa_tb)

twa_tb %>%
  group_by(방법, 온도) %>%  # 방법, 온도 그룹쪼개서 확인(총 네개의 그룹)
  get_summary_stats(맛점수)
 
get_summary_stats(맛점수) 하면 아래와 같이 기초통계 확인 가능
 
# A tibble: 4 × 15
  방법  온도  variable     n   min   max median    q1    q3   iqr   mad  mean    sd    se    ci
  <fct> <fct> <fct>    <dbl> <dbl> <dbl>  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 오븐  200도 맛점수      14    84    91   87.5  86.2  89    2.75  2.22  87.5  2.03 0.542 1.17 
2 오븐  300도 맛점수      16    91    98   94    92.8  95.2  2.5   2.22  94.2  2.04 0.51  1.09 
3 기름  200도 맛점수      15    90    98   94    92.5  95.5  3     2.96  94    2.30 0.594 1.27 
4 기름  300도 맛점수      15    84    88   86    85    87    2     1.48  86    1.20 0.309 0.662
 
 
# 그래프 그리기
# 박스플랏, 히스토그램, 상호작용 그래프
twa_tb %>%
  ggplot(mapping = aes(x = 방법,
                       y = 맛점수,
                       color = 방법)) + # 방법에 따라 색상을 다르게 해줘 
  geom_boxplot() +
  facet_wrap(~온도) # 온도에 따라 그래프 따로 그려서 보여줘

twa_tb %>%
  ggplot(mapping = aes(x = 맛점수)) +
  geom_histogram(bins = 10,
                 color = "white",
                 fill = "steelblue",) +
  facet_wrap(~ 방법*온도) 방법과 온도에 따라 그래프를 각각 그려서 보여줘

twa_tb %>%
  group_by(온도, 방법) %>% # 온도에 따라 그룹핑 한 후에 방법에 따라 그룹핑한다
  summarise(맛점수 = mean(맛점수)) %>% # 각 그룹의 맛점수 평균을 구하는 전처리 후, 그 값을 가지고 그래프를 그릴거야
  ggplot(mapping = aes(x = 온도, 
                       y = 맛점수,
                       color = 방법)) + # 방법에 따라 색깔 다르게
  geom_line(mapping = aes(group = 방법)) + # 방법에 따라 나누어서 직선 그려줘
  geom_point() # cross-over 됨, interaction effect가 있는 것으로 보임
# 200도에서는 기름일 때, 300도에서는 오븐일 때 맛점수가 좋게 나타남
# 다음 단계에서 이 상호작용 효과가 통계적으로도 나타나는가를 살펴볼 것임
박스플랏
히스토그램
 
interaction effect 그래프

 

 

 

 

3. 이상치 제거

 
통계분석을 위해 분포에서 벗어나는 극단적인 값, 이상치를 제거해야 함. identify_outliers() 함수를 활용하면 간단히 파악 가능. 
박스플랏에 나타나지 않았던 이상치가 나타나기도 함.
 
# 각각의 그룹을 나누어서 이상치 확인
twa_tb %>%
  group_by(방법, 온도) %>%
  identify_outliers(맛점수) 
 
이상치 없음
[1] 방법       온도       맛점수     is.outlier is.extreme
<0 rows> (or 0-length row.names)
 
 
 
 
 
 
 

 

 

 

 

 

 

 

 

4. 샤피로 테스트: 정규분포검정

  • 통계분석은 데이터의 분포가 정규분포일 것을 가정하고 이루어짐. 따라서 통계분석을 위해서는 이 데이터의 분포가 정규분포를 따르는지 검정해보아야 함.
  • 그럴때 사용되는 것이 샤피로 테스트.  샤피로 테스트의 귀무가설은 '이 데이터의 분포가 정규분포를 따른다'는 것이고, 반대되는 대체가설은 '정규분포를 따르지 않는다' 가 됨. 샤피로 테스트의 p밸류 값이 0.05 이상이라면 귀무가설이 채택되면서 정규분포를 따른다고 볼 수 있음
  • shapiro_test() 함수를 활용하면 됨
  • 독립표본 t-검정에서는 각각의 그룹에 대해 확인해야 함
# 정규분포 검정
twa_tb %>%
  group_by(방법, 온도) %>%
  shapiro_test(맛점수) # 모두 정규분포
 
위의 코드 입력 결과 아래와 같이 출력됨. 다 p밸류 0.05 이상이기 때문에 귀무가설이 채택됨. 즉, 이 데이터의 분포가 정규분포라고 받아들일 수 있음. 
 
# A tibble: 4 × 5
  방법  온도  variable statistic     p
  <fct> <fct> <chr>        <dbl> <dbl>
1 오븐  200도 맛점수       0.970 0.876
2 오븐  300도 맛점수       0.961 0.683
3 기름  200도 맛점수       0.967 0.817
4 기름  300도 맛점수       0.918 0.181
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 

5. 등분산검정

 
르벤테스트 실시, 귀무가설: 이 분포들은 등분산성을 가진다
 
twa_tb %>%
  levene_test(맛점수 ~ 방법*온도)
 
p밸류 0.05 이상 → 귀무가설 채택 → 등분산성 가진다
 
# A tibble: 1 × 4
    df1   df2 statistic     p
  <int> <int>     <dbl> <dbl>
1     3    56      1.46 0.235
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 

 

 

 

 

 

6. 통계분석 : ANOVA

 
이제 시점 간 차이가 있다는 것은 알았는데 어느 시점 간에 차이가 있는지를 보고자 함. 아래의 코드 실행하여 ANOVA 테스트.
twa_results <- aov(맛점수 ~ 방법*온도,
                   data = twa_tb)
tidy(twa_results) # 상호작용 있음 -> 사후검정
 
 
그 결과는 아래와 같음. 
“방법:온도”는 상호작용을 보는 부분임. 귀무가설 기각 → 상호작용이 유의하게 나타났다~~
 
# A tibble: 4 × 6
  term         df  sumsq meansq statistic   p.value
  <chr>     <dbl>  <dbl>  <dbl>     <dbl>     <dbl>
1 방법          1  17.1   17.1       4.55  3.73e- 2
2 온도          1   6.77   6.77      1.81  1.84e- 1
3 방법:온도     1 807.   807.      215.    7.70e-21
4 Residuals    56 210.     3.75     NA    NA
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 

7. 사후검정: 다중비교

 
사후검정을 통해 구체적으로 그룹 간에 얼마나 차이가 있나 보자
 
twa_tb %>%
  group_by(온도) %>% # 온도에 따른 방법의 차이가 있는가를 보겠다
  pairwise_t_test(맛점수 ~ 방법, 
                  p.adj = "bonferroni") # 기름은 200도에서 오븐은 300도에서 결과가 좋았다
 
200도 오븐-기름, 300도 오븐-기름 둘 다 큰 차이가 있음
 
# A tibble: 2 × 10
  온도  .y.    group1 group2    n1    n2        p p.signif    p.adj p.adj.signif
* <fct> <chr>  <chr>  <chr>  <int> <int>    <dbl> <chr>       <dbl> <chr>       
1 200도 맛점수 오븐   기름      14    15 1.20e- 8 ****     1.20e- 8 ****        
2 300도 맛점수 오븐   기름      16    15 4.81e-14 ****     4.81e-14 ****     
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 

 

8. 부록: 상호작용이 없을 경우

 
twa_results <- aov(맛점수 ~ 방법 + 온도, 
                   data = twa_tb)

tidy(twa_results)
 
방법에 따라 맛점수 차이 없음, 온도에 따라 맛점수 차이없음
# A tibble: 3 × 6
  term         df   sumsq meansq statistic p.value
  <chr>     <dbl>   <dbl>  <dbl>     <dbl>   <dbl>
1 방법          1   17.1   17.1      0.956   0.332
2 온도          1    6.77   6.77     0.379   0.540
3 Residuals    57 1017.    17.8     NA      NA    
 
t-test 진행
twa_tb %>%
  pairwise_t_test(맛점수 ~ 방법,
                  p.adj = "bonferroni") # 오븐- 기름 맛점수 차이 없음
 
# A tibble: 1 × 9
  .y.    group1 group2    n1    n2     p p.signif p.adj p.adj.signif
* <chr>  <chr>  <chr>  <int> <int> <dbl> <chr>    <dbl> <chr>       
1 맛점수 오븐   기름      30    30  0.33 ns        0.33 ns