13. 분산분석

Statistics
교재 9장
Author

Kim Jae Sook

Published

February 4, 2024

분산분석(analysis of variance, ANOVA)은 분산을 분석하기 때문에 지어진 이름이지만 그 목적은 평균을 분석하는 것이다. 여러 집단의 평균이 같은지, 아니면 하나라도 평균이 다른 집단이 있는지 판단하려는 것이 목적이다.

[엑셀] 실습하기

  • 분산분석 (sasa메일로 로그인해야 내용을 볼 수 있습니다.)

[R기초] 실습하기

F 분포(\(X \sim F(df1, df2)\))

  • \(V_1\), \(V_2\)가 서로 독립이고, 자유도가 각각 \(d_1\)\(d_2\)인 카이제곱(\(\chi^2\)) 분포를 따를 때, \(F= \dfrac{V_1 / d_1}{V_2 /d_2}\)의 분포를 자유도가 \((d_1 , d_2 )\)\(F\)분포라 한다.

  • F분포는 분자의 자유도 \(d_1\)과 분모의 자유도 \(d_2\) 두 개의 자유도에 의해 분포가 유일하게 결정된다. 아래 그림과 같이 분자와 분모의 자유도가 모두 커지면 좌우대칭인 분포를 따르는 형태가 나온다.

* 그림 출처: 통계교육원, R을 활용한 통계분석

  • R에서 제공되는 F분포와 관련된 함수

  • df() : \(P(X=x)\)

  • pf() : \(P(X<x)\) 또는 \(P(X \leq x)\)

  • qf() : \(P(X<x)=p\)가 되는 \(x\)

  • rf() : 주어진 카이제곱에서 난수를 뽑는 방법

# chi_squares distribution
df(1, df1=5, df2=2) # 분자의 자유도가 5, 분모의 자유도가 2인 F분포에서 X=1에서의 확률
[1] 0.3080008
pf(1, df1=5, df2=2, lower.tail = T) # 분자의 자유도가 5, 분모의 자유도가 2인 F분포에서 X가 1보다 작을 확률
[1] 0.4312012
pf(1, df1=5, df2=2, lower.tail = F) # 분자의 자유도가 5, 분모의 자유도가 2인 F분포에서 X가 1보다 클 확률
[1] 0.5687988
qf(0.05, df1=5, df2=2, lower.tail = T) # 분자의 자유도가 5, 분모의 자유도가 2인 F분포에서 확률이 0.05일때의 x값
[1] 0.1728269
qf(0.95, df1=5, df2=2, lower.tail = T) # 분자의 자유도가 5, 분모의 자유도가 2인 F분포에서 확률이 0.95일때의 x값
[1] 19.29641
sample = rf(1000, df1=5, df2=2) # 자유도가 4인 카이제곱분포에서 1000개의 수를 임의로 뽑기
hist(sample, breaks = c(-1:round(max(sample))+1), xlim=c(-1,15)) # 히스토그램 그리기

모수적 일원배치 분산분석

일원배치 분산분석(One-way analysis of variance(ANOVA))이란?

  • 일반적으로 3개 이상의 모집단에서 모평균을 비교하는 문제에서 사용되며, 이때 사용되는 변수는 두 가지로 분류된다. 한 변수는 범주형 변수(3가지 이상의 범주값)이고, 평균을 비교하고자 하는 변수는 수치형 변수(평균 비교에 사용되는 변수)이다.

  • 평균을 비교하기 전에 세 집단의 분포가 정규분포인지, 집단 간 분산이 동일한지에 따라 그 결과가 다르다. 따라서 정규성 검정과 등분산성 검정을 먼저 실시하고 그 결과에 따라 평균을 비교하는 방법으로 진행한다.

  • 일원배치 분산분석은 평균에 차이가 있다, 없다만 판단 가능하며 어느 집단끼리 차이가 있는지에 대해서는 알 수 없다. 3개 이상의 평균 차이가 있다면 사후 분석이라는 다중비교를 할 수 있다.

  • 여러가지 다중비교 방법 중 Tukey HSD 검정이 있다.

  • 세 가지 이상 집단의 평균비교임에도 평균비교라고 하지 않고 분산분석이라고 하는 이유는 분산비를 이용하여 평균 차이를 검정하기 때문이다.

  • 분산분석 실험의 목적은 독립변수가 종속변수에 어떤 영향을 미치는지 알아보는 것이다.

Cars93데이터셋에서 에어백 유무에 따른 가격에 대한 일원배치 분산분석

  • 에어백 유무의 3가지 범주: 에어백 없음, 운전석 에어백, 운전석과 조수석 에어백

# one-way ANalysis Of VAriance (ANOVA)
library(MASS)
Cars93$AirBags  # group variable = independent variable
 [1] None               Driver & Passenger Driver only        Driver & Passenger
 [5] Driver only        Driver only        Driver only        Driver only       
 [9] Driver only        Driver only        Driver & Passenger None              
[13] Driver only        Driver & Passenger None               None              
[17] None               Driver only        Driver only        Driver & Passenger
[21] Driver & Passenger Driver only        None               Driver only       
[25] Driver only        Driver only        Driver only        Driver only       
[29] None               Driver & Passenger None               None              
[33] None               Driver only        Driver only        Driver only       
[37] Driver only        Driver only        None               Driver only       
[41] Driver & Passenger Driver only        Driver & Passenger None              
[45] None               None               None               Driver only       
[49] Driver only        Driver & Passenger Driver & Passenger Driver & Passenger
[53] None               None               Driver only        None              
[57] Driver only        Driver only        Driver & Passenger Driver only       
[61] None               None               Driver only        Driver only       
[65] Driver only        None               Driver only        None              
[69] Driver only        None               Driver only        None              
[73] None               None               Driver & Passenger None              
[77] Driver & Passenger Driver only        Driver only        None              
[81] None               Driver only        None               Driver only       
[85] Driver only        Driver only        Driver only        None              
[89] None               None               None               Driver only       
[93] Driver & Passenger
Levels: Driver & Passenger Driver only None
Cars93$Price    # dependent variable
 [1] 15.9 33.9 29.1 37.7 30.0 15.7 20.8 23.7 26.3 34.7 40.1 13.4 11.4 15.1 15.9
[16] 16.3 16.6 18.8 38.0 18.4 15.8 29.5  9.2 11.3 13.3 19.0 15.6 25.8 12.2 19.3
[31]  7.4 10.1 11.3 15.9 14.0 19.9 20.2 20.9  8.4 12.5 19.8 12.1 17.5  8.0 10.0
[46] 10.0 13.9 47.9 28.0 35.2 34.3 36.1  8.3 11.6 16.5 19.1 32.5 31.9 61.9 14.1
[61] 14.9 10.3 26.1 11.8 15.7 19.1 21.5 13.5 16.3 19.5 20.7 14.4  9.0 11.1 17.7
[76] 18.5 24.4 28.7 11.1  8.4 10.9 19.5  8.6  9.8 18.4 18.2 22.7  9.1 19.7 20.0
[91] 23.3 22.7 26.7
# dist~ of Airbags
table(Cars93$AirBags)

Driver & Passenger        Driver only               None 
                16                 43                 34 
# Price normality test for AirBags: 세 가지 모두 검정결과 정규분포 따르지 않으나 표본수가 많으므로 중심극한정리에 의해 정규성을 가정해도 됨.
shapiro.test(Cars93$Price[Cars93$AirBags =='None'])

    Shapiro-Wilk normality test

data:  Cars93$Price[Cars93$AirBags == "None"]
W = 0.92329, p-value = 0.02004
shapiro.test(Cars93$Price[Cars93$AirBags =='Driver only'])

    Shapiro-Wilk normality test

data:  Cars93$Price[Cars93$AirBags == "Driver only"]
W = 0.93184, p-value = 0.01345
shapiro.test(Cars93$Price[Cars93$AirBags =='Driver & Passenger'])

    Shapiro-Wilk normality test

data:  Cars93$Price[Cars93$AirBags == "Driver & Passenger"]
W = 0.8631, p-value = 0.02136
# Price equal variance test for AirBags : levene.test(), Bartlett()
library(lawstat)
Warning: package 'lawstat' was built under R version 4.3.3
levene.test(Cars93$Price, Cars93$AirBags) #검정결과 등분산 아님

    Modified robust Brown-Forsythe Levene-type test based on the absolute
    deviations from the median

data:  Cars93$Price
Test Statistic = 8.1213, p-value = 0.0005721
bartlett.test(Cars93$Price ~ Cars93$AirBags) #검정결과 등분산 아님

    Bartlett test of homogeneity of variances

data:  Cars93$Price by Cars93$AirBags
Bartlett's K-squared = 24.899, df = 2, p-value = 3.92e-06
# normality, equal variance(평소 많이 가정하는 것)
## one-way ANOVA(집단간 평균비교)
aggregate(Price ~ AirBags, Cars93, base::mean) #에어백 여부에 따른 가격의 평균 계산
             AirBags    Price
1 Driver & Passenger 28.36875
2        Driver only 21.22326
3               None 13.17353
## if equal variance : aov()   oneway.test()
result = aov(Price ~ AirBags, data=Cars93) #검정결과 각 집단간에 적어도 하나의 그룹은 평균이 다르다 할 수 있음
summary(result)
            Df Sum Sq Mean Sq F value  Pr(>F)    
AirBags      2   2747  1373.5   21.18 2.9e-08 ***
Residuals   90   5837    64.9                    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
oneway.test(Price ~ AirBags, data=Cars93, var.equal = T) #위와 같은 결과임

    One-way analysis of means

data:  Price and AirBags
F = 21.178, num df = 2, denom df = 90, p-value = 2.901e-08
## if no equal vaiance : oneway.test()
oneway.test(Price ~ AirBags, data=Cars93, var.equal = F) #검정결과 각 집단간에 적어도 하나의 그룹은 평균이 다르다 할 수 있음

    One-way analysis of means (not assuming equal variances)

data:  Price and AirBags
F = 23.082, num df = 2.000, denom df = 34.479, p-value = 4.35e-07
## TukeyHSD() : post Hoc if reject HO of one-way ANOVA [사후검정]
## equal variance 가정 ==> aov함수 사용하기
result = aov(Price ~ AirBags, data=Cars93)
TukeyHSD(result) #검정결과 세 그룹 모두 가격 평균이 다르다 할 수 있음
  Tukey multiple comparisons of means
    95% family-wise confidence level

Fit: aov(formula = Price ~ AirBags, data = Cars93)

$AirBags
                                     diff       lwr       upr     p adj
Driver only-Driver & Passenger  -7.145494 -12.76566 -1.525327 0.0088790
None-Driver & Passenger        -15.195221 -21.01361 -9.376828 0.0000000
None-Driver only                -8.049726 -12.45415 -3.645302 0.0001033
plot(TukeyHSD(result, "AirBags"))

비모수적 일원배치 분산분석

비모수적 일원배치 분산분석이란?

  • 비모수적 검정(크루스칼-왈리스 검정, Kruskal-Wallis test)은 세 집단 이상의 평균을 비교할 때, 각 집단에서 정규성 검정을 만족하지 못하거나 소표본인 경우 실행하며 순위평균의 차이 여부를 가지고 모집단의 평균 차이 여부를 알아본다.

Cars93데이터셋에서 에어백 유무에 따른 가격에 대한 일원배치 분산분석

  • 에어백 유무의 3가지 범주: 에어백 없음, 운전석 에어백, 운전석과 조수석 에어백

## Kruskal-wallis test : non-parametric test
library(MASS)
table(Cars93$AirBags)

Driver & Passenger        Driver only               None 
                16                 43                 34 
aggregate(Price~AirBags, Cars93, base::mean)
             AirBags    Price
1 Driver & Passenger 28.36875
2        Driver only 21.22326
3               None 13.17353
# normality test : alpha = 0.05 ==> 0.01 ??(유의수준을 0.01로 변경하면 모든 그룹이 정규성을 따름)
tapply(Cars93$Price, Cars93$AirBags, shapiro.test)
$`Driver & Passenger`

    Shapiro-Wilk normality test

data:  X[[i]]
W = 0.8631, p-value = 0.02136


$`Driver only`

    Shapiro-Wilk normality test

data:  X[[i]]
W = 0.93184, p-value = 0.01345


$None

    Shapiro-Wilk normality test

data:  X[[i]]
W = 0.92329, p-value = 0.02004
# if HO reject ==> Kruskal-wallis test(정규성을 만족하지 않으면 비모수적 검정)
## Kruskal Wallis test : HO: means for all groups equal

kruskal.test(Price ~ AirBags, data=Cars93) # 검정결과 적어도 하나의 그룹은 다른 그룹과 차이가 있음

    Kruskal-Wallis rank sum test

data:  Price by AirBags
Kruskal-Wallis chi-squared = 32.639, df = 2, p-value = 8.175e-08
## mutiple comparison or Post Hoc test [사후검정]
### parametric test : Tukey, Scheffe, Games-Howell, Tukey's Honest Significant Difference(HSD)
### non-parametric test : 1) density plot for grop   2) dunn.test   3) mctp()

### 1) density plot: moonBook package
# install.packages("moonBook") # moomBook패키지가 없으면 주석 지우고 설치하기
library(moonBook)
Warning: package 'moonBook' was built under R version 4.3.3
densityplot(Price~AirBags, data=Cars93) #그래프를 보는 방법으로 주관적임

 ' Price ' is an invalid column name: Instead ' Min.Price ' is used
### 2) Ddunn's multiple comparison test: dunn.test package
# install.packages('dunn.test') # dunn.test패키지가 없으면 주석 지우고 설치하기
library(dunn.test)
dunn.test(Cars93$Price, Cars93$AirBags, method='bonferroni')
  Kruskal-Wallis rank sum test

data: x and group
Kruskal-Wallis chi-squared = 32.6393, df = 2, p-value = 0

                           Comparison of x by group                            
                                 (Bonferroni)                                  
Col Mean-|
Row Mean |   Driver &   Driver o
---------+----------------------
Driver o |   1.717373
         |     0.1289
         |
    None |   5.078861   4.517930
         |    0.0000*    0.0000*

alpha = 0.05
Reject Ho if p <= alpha/2
## 3) mctp(): nparcomp package, 정규분포이고 등분산 아닐때 사용
# install.packages('nparcomp') # nparcomp패키지가 없으면 주석 지우고 설치하기
library(nparcomp)
Warning: package 'nparcomp' was built under R version 4.3.3
Loading required package: multcomp
Warning: package 'multcomp' was built under R version 4.3.3
Loading required package: mvtnorm
Warning: package 'mvtnorm' was built under R version 4.3.3
Loading required package: survival
Loading required package: TH.data
Warning: package 'TH.data' was built under R version 4.3.3

Attaching package: 'TH.data'
The following object is masked from 'package:MASS':

    geyser

result = mctp(Price ~ AirBags, data=Cars93)  # tukey default

 #----------------Nonparametric Multiple Comparisons for relative effects---------------# 
 
 - Alternative Hypothesis:  True differences of relative effects are not equal to 0 
 - Estimation Method:  Global Pseudo Ranks 
 - Type of Contrast : Tukey 
 - Confidence Level: 95 % 
 - Method = Fisher with 28 DF 
 
 #--------------------------------------------------------------------------------------# 
 
summary(result)

 #----------------Nonparametric Multiple Comparisons for relative effects---------------# 
 
 - Alternative Hypothesis:  True differences of relative effects are not equal to 0 
 - Estimation Method: Global Pseudo ranks 
 - Type of Contrast : Tukey 
 - Confidence Level: 95 % 
 - Method = Fisher with 28 DF 
 
 #--------------------------------------------------------------------------------------# 
 
 #----Data Info-------------------------------------------------------------------------# 
              Sample Size    Effect     Lower     Upper
1 Driver & Passenger   16 0.6950239 0.6310752 0.7522398
2        Driver only   43 0.5464974 0.4880819 0.6036599
3               None   34 0.2584787 0.2201847 0.3008632

 #----Contrast--------------------------------------------------------------------------# 
       1  2 3
2 - 1 -1  1 0
3 - 1 -1  0 1
3 - 2  0 -1 1

 #----Analysis--------------------------------------------------------------------------# 
      Estimator  Lower  Upper Statistic      p.Value
2 - 1    -0.149 -0.310  0.021    -2.153 9.326285e-02
3 - 1    -0.437 -0.555 -0.301    -7.298 4.041749e-08
3 - 2    -0.288 -0.402 -0.166    -5.632 1.217733e-05

 #----Overall---------------------------------------------------------------------------# 
  Quantile      p.Value
1 2.454117 4.041749e-08

 #--------------------------------------------------------------------------------------# 

간단하게 살펴보는 일원배치분산분석 예제

자동차 충돌실험 결과 여러 등급의 자동차에서 인형의 파손 정도

  • 자동차 충돌실험의 결과 인형의 파손 정도가 다음과 같다. 이 데이터를 사용하여 인형의 파손 정도는 자동차의 크기에 관계없이 동일하다는 귀무가설을 검정하시오.
소형자동차 준중형자동차 중형자동차 대형자동차
681 643 469 384
728 655 727 656
917 742 525 602
898 514 454 687
620 525 459 360
평균 768.8 615.8 526.8 537.8
표준편차 132.4 95.9 115.5 154.6
y <- c(681, 728, 917, 898, 620,
       643, 655, 742, 514, 525,
       469, 727, 525, 454, 459,
       384, 656, 602, 687, 360) 
 
x <- rep(c("소형","준중형","중형","대형"), c(5,5,5,5))
x <-factor(x)

aov.result=aov(y ~ x)
summary(aov.result)
            Df Sum Sq Mean Sq F value Pr(>F)  
x            3 186825   62275   3.893  0.029 *
Residuals   16 255923   15995                 
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# F통계량값인 3.8934가 기각역에 있으므로 귀무가설을 기각한다.
# 또는 p값 0.029가 유의수준 0.05보다 작으므로 귀무가설을 기각한다.
# 자동차의 크기에 따른 등급은 인형모형의 파손 정도에 통계적으로 유의한 차이를 보인다.

이원배치분산분석

이원배치분산분석(Two-way analysis of variance(ANOVA))이란

Cars93데이터셋에서 에어백 유무와 미국회사 유무에 따른 가격에 대한 이원배치 분산분석

  • 균형자료라고 가정하고 검정하기
# two-way ANOVA 

library(MASS)  # Cars93
## factor1 : AirBags
## factor2 : Origin 
## dependent variable : Price

replications(Price ~ AirBags * Origin, Cars93) #균형설계자료인지 확인(각 범주별로 자료수가 동일한지)
$AirBags
AirBags
Driver & Passenger        Driver only               None 
                16                 38                 28 

$Origin
Origin
    USA non-USA 
     42      40 

$`AirBags:Origin`
                    Origin
AirBags              USA non-USA
  Driver & Passenger   9       7
  Driver only         20      18
  None                13      15
aggregate(Price~AirBags, Cars93, base::mean) #평균 비교해보기
             AirBags    Price
1 Driver & Passenger 28.36875
2        Driver only 21.22326
3               None 13.17353
aggregate(Price~Origin, Cars93, base::mean) #평균 비교해보기
   Origin    Price
1     USA 18.57292
2 non-USA 20.50889
## two-way  anova :  parametric method , balanced data(지금 자료가 불균형이지만 균형자료라고 가정하고 검정)
### 1) for factor1 HO: All means are equal
### 2) for facotr2 HO: all means are equal
### 3) for interaction factor1*factor2 : HO: all means are equal
## method1(모수적 방법1)
result = aov(Price ~ AirBags * Origin, data= Cars93) #정규성,등분산성을 만족한다고 가정하고 분산분석 실시
summary(result)
               Df Sum Sq Mean Sq F value   Pr(>F)    
AirBags         2   2747  1373.5  21.925 1.95e-08 ***
Origin          1    170   170.3   2.719    0.103    
AirBags:Origin  2    217   108.4   1.730    0.183    
Residuals      87   5450    62.6                     
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## method2 (모수적 방법2)
anova(lm(Price ~ AirBags * Origin, data=Cars93))
Analysis of Variance Table

Response: Price
               Df Sum Sq Mean Sq F value    Pr(>F)    
AirBags         2 2747.0 1373.49 21.9254 1.947e-08 ***
Origin          1  170.3  170.31  2.7186    0.1028    
AirBags:Origin  2  216.7  108.35  1.7296    0.1834    
Residuals      87 5450.0   62.64                      
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
  • 위 검정 결과, 에어벡 여부에 따른 각 집단간의 평균은 적어도 하나는 다르고, 미국회사 유무에 따른 각 집단의 평균은 모두 같다. 또한 에어백 여부와 미국회사 유무의 상호작용에 따른 각 집단의 평균은 모두 같다.

  • 위 자료가 불균형자료인데, 균형자료라고 가정하고 검정했다. 균형자료일 경우에는 아래 그림에서 aov, anova 함수의 기본옵션인 type2로 계산한다. 불균형자료는 type3로 계산해야 한다.

## two-way ANOVA for  unbalanced data  : Type3 SS
### Anova()  ==> car package 
# install.packages('car')  # car 라이브러리가 없으면 주석 지우고 설치하기
library(car)
Warning: package 'car' was built under R version 4.3.3
Loading required package: carData
Warning: package 'carData' was built under R version 4.3.3

Attaching package: 'car'
The following object is masked from 'package:lawstat':

    levene.test
result = aov(Price ~ AirBags * Origin, data= Cars93)
Anova(result, type=3)  # 검정결과 미국회사유무에 따라서도 가격 차이가 있음
Warning in printHypothesis(L, rhs, names(b)): one or more coefficients in the hypothesis include
     arithmetic operators in their names;
  the printed representation of the hypothesis will be omitted
Warning in printHypothesis(L, rhs, names(b)): one or more coefficients in the hypothesis include
     arithmetic operators in their names;
  the printed representation of the hypothesis will be omitted
Anova Table (Type III tests)

Response: Price
               Sum Sq Df F value    Pr(>F)    
(Intercept)    5436.6  1 86.7857 1.013e-14 ***
AirBags         802.8  2  6.4076  0.002535 ** 
Origin          295.6  1  4.7194  0.032544 *  
AirBags:Origin  216.7  2  1.7296  0.183391    
Residuals      5450.0 87                      
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## plot for interaction effect(상호작용 효과가 있을때 그려보기)
interaction.plot(Cars93$AirBags, Cars93$Origin, Cars93$Price)

비모수적 방법(프리드만 검정, freidman test)

  • 주조시간에 따라 강도에 차이가 있는지 검정하자.(소표본)

## non-parametric : two-way ANOVA  ==> freidman test
## factor1: independent variable
## factor2: block(실험에서 차이가 있어도 되고 없어도 될때 block이라 함)
## dependent variable 

data = read.csv("strength.csv", header = T)  # 첫번째행에 변수명 있음
str(data)  # 자료 구조 살피기
'data.frame':   9 obs. of  3 variables:
 $ A      : chr  "A1" "A1" "A1" "A2" ...
 $ B      : chr  "B1" "B2" "B3" "B1" ...
 $ strenth: int  90 95 100 100 94 100 104 110 113
friedman.test(data$strenth, data$A, data$B)

    Friedman rank sum test

data:  data$strenth, data$A and data$B
Friedman chi-squared = 4.9091, df = 2, p-value = 0.0859

반복측정 분산분석

반복측정 분산분석이란

실습예제

  • 주변 이산화탄소의 여러 농도에 따른 나무의 이산화탄소 흡수율 비교
## repeated measure ANOVA

## 1. one - repeated factor, dependent variable(사전에 정규성, 등분산성 검증은 사전에 실시해야 함)
## 'CO2' 

str(CO2)
Classes 'nfnGroupedData', 'nfGroupedData', 'groupedData' and 'data.frame':  84 obs. of  5 variables:
 $ Plant    : Ord.factor w/ 12 levels "Qn1"<"Qn2"<"Qn3"<..: 1 1 1 1 1 1 1 2 2 2 ...
 $ Type     : Factor w/ 2 levels "Quebec","Mississippi": 1 1 1 1 1 1 1 1 1 1 ...
 $ Treatment: Factor w/ 2 levels "nonchilled","chilled": 1 1 1 1 1 1 1 1 1 1 ...
 $ conc     : num  95 175 250 350 500 675 1000 95 175 250 ...
 $ uptake   : num  16 30.4 34.8 37.2 35.3 39.2 39.7 13.6 27.3 37.1 ...
 - attr(*, "formula")=Class 'formula'  language uptake ~ conc | Plant
  .. ..- attr(*, ".Environment")=<environment: R_EmptyEnv> 
 - attr(*, "outer")=Class 'formula'  language ~Treatment * Type
  .. ..- attr(*, ".Environment")=<environment: R_EmptyEnv> 
 - attr(*, "labels")=List of 2
  ..$ x: chr "Ambient carbon dioxide concentration"
  ..$ y: chr "CO2 uptake rate"
 - attr(*, "units")=List of 2
  ..$ x: chr "(uL/L)"
  ..$ y: chr "(umol/m^2 s)"
# dependent variable : uptake(이산화탄소 흡수율)
# repeated factor : conc(이산화탄소 농도)

head(CO2)
  Plant   Type  Treatment conc uptake
1   Qn1 Quebec nonchilled   95   16.0
2   Qn1 Quebec nonchilled  175   30.4
3   Qn1 Quebec nonchilled  250   34.8
4   Qn1 Quebec nonchilled  350   37.2
5   Qn1 Quebec nonchilled  500   35.3
6   Qn1 Quebec nonchilled  675   39.2
boxplot(formula = uptake~conc, data=CO2) # 이산화탄소 농도에 따른 이산화탄소 흡수율의 상자그림

means = aggregate(uptake~conc, CO2, base::mean)
means
  conc   uptake
1   95 12.25833
2  175 22.28333
3  250 28.87500
4  350 30.66667
5  500 30.87500
6  675 31.95000
7 1000 33.58333
## repeated ANOVA 
## H0: means of uptake for conc are same

result = aov(uptake ~ conc + Error(Plant/conc), data=CO2) # conc factor는 반복측정되므로 오차항에 Error(Plant/conc)로 넣어줘야 함
summary(result) # H0기각, 주변 이산화탄소 농도에 따른 이산화탄소 흡수율에는 차이가 있다고 할 수 있음

Error: Plant
          Df Sum Sq Mean Sq F value Pr(>F)
Residuals 11   4862     442               

Error: Plant:conc
          Df Sum Sq Mean Sq F value   Pr(>F)    
conc       1 2285.0  2285.0   70.39 4.14e-06 ***
Residuals 11  357.1    32.5                     
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Error: Within
          Df Sum Sq Mean Sq F value Pr(>F)
Residuals 60   2203   36.71               
## cf one-way ANOVA
result1 = aov(uptake ~ conc, data=CO2)
summary(result1) # 반복이 없는 분산분석의 MSE는 90.5, 반복측정분산분석의 MSE는 32.5로 반복측정 시, F값의 분모인 MSE가 더 작으므로 검정력이 높음
            Df Sum Sq Mean Sq F value   Pr(>F)    
conc         1   2285  2285.0   25.25 2.91e-06 ***
Residuals   82   7422    90.5                     
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## Post-Hoc test

with(CO2, pairwise.t.test(uptake, conc, paired=T, p.adjust.method='bonferroni'))

    Pairwise comparisons using paired t tests 

data:  uptake and conc 

     95      175     250     350     500     675    
175  0.00025 -       -       -       -       -      
250  0.00012 0.00736 -       -       -       -      
350  0.00013 0.00098 0.53879 -       -       -      
500  0.00012 0.00268 0.01458 1.00000 -       -      
675  4.5e-05 0.00052 0.00210 0.83520 0.76607 -      
1000 7.5e-05 0.00059 0.00253 0.01468 0.01741 0.10482

P value adjustment method: bonferroni 

- 저온처리 유무가 추가되었을때, 주변 이산화탄소의 여러 농도에 따른 나무의 이산화탄소 흡수율 비교

## one factor, one repeated factor ==> two-way repeated ANOVA
## Treatment(저온처리 유무), conc(주변 이산화탄소 농도) 

head(CO2)
  Plant   Type  Treatment conc uptake
1   Qn1 Quebec nonchilled   95   16.0
2   Qn1 Quebec nonchilled  175   30.4
3   Qn1 Quebec nonchilled  250   34.8
4   Qn1 Quebec nonchilled  350   37.2
5   Qn1 Quebec nonchilled  500   35.3
6   Qn1 Quebec nonchilled  675   39.2
aggregate(uptake~conc, CO2, base::mean)
  conc   uptake
1   95 12.25833
2  175 22.28333
3  250 28.87500
4  350 30.66667
5  500 30.87500
6  675 31.95000
7 1000 33.58333
aggregate(uptake~Treatment, CO2, base::mean)
   Treatment   uptake
1 nonchilled 30.64286
2    chilled 23.78333
result3 = aov(uptake~Treatment*conc + Error(Plant/conc), data=CO2)
summary(result3)

Error: Plant
          Df Sum Sq Mean Sq F value Pr(>F)
Treatment  1    988   988.1   2.551  0.141
Residuals 10   3874   387.4               

Error: Plant:conc
               Df Sum Sq Mean Sq F value  Pr(>F)    
conc            1 2285.0  2285.0   70.27 7.8e-06 ***
Treatment:conc  1   31.9    31.9    0.98   0.346    
Residuals      10  325.2    32.5                    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Error: Within
          Df Sum Sq Mean Sq F value Pr(>F)
Residuals 60   2203   36.71               
## cf  two-way ANOVA
result4 = aov(uptake~Treatment*conc, data=CO2)
summary(result4)
               Df Sum Sq Mean Sq F value   Pr(>F)    
Treatment       1    988   988.1  12.348  0.00073 ***
conc            1   2285  2285.0  28.554 8.38e-07 ***
Treatment:conc  1     32    31.9   0.398  0.52979    
Residuals      80   6402    80.0                     
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1