7.4 ANOVA
7.4.1 问题
你想要使用 ANOVA 比较多组之间的差异。
7.4.2 方案
假设这是你的数据:
data <- read.table(header = TRUE, text = "
subject sex age before after
1 F old 9.5 7.1
2 M old 10.3 11.0
3 M old 7.5 5.8
4 F old 12.4 8.8
5 M old 10.2 8.6
6 M old 11.0 8.0
7 M young 9.1 3.0
8 F young 7.9 5.2
9 F old 6.6 3.4
10 M young 7.7 4.0
11 M young 9.4 5.3
12 M old 11.6 11.3
13 M young 9.9 4.6
14 F young 8.6 6.4
15 F young 14.3 13.5
16 F old 9.2 4.7
17 M young 9.8 5.1
18 F old 9.9 7.3
19 F young 13.0 9.5
20 M young 10.2 5.4
21 M young 9.0 3.7
22 F young 7.9 6.2
23 M old 10.1 10.0
24 M young 9.0 1.7
25 M young 8.6 2.9
26 M young 9.4 3.2
27 M young 9.7 4.7
28 M young 9.3 4.9
29 F young 10.7 9.8
30 M old 9.3 9.4
")
# 确保 subject
# 列是一个因子变量,这样不会当作连续变量对待
data$subject <- factor(data$subject)
7.4.2.1 单因素 ANOVA 分析
# 单因素: 独立变量: sex 依赖变量: before
aov1 <- aov(before ~ sex, data = data)
summary(aov1)
#> Df Sum Sq Mean Sq F value Pr(>F)
#> sex 1 1.5 1.53 0.57 0.46
#> Residuals 28 74.7 2.67
# 显示均值
model.tables(aov1, "means")
#> Tables of means
#> Grand mean
#>
#> 9.703
#>
#> sex
#> F M
#> 10 9.532
#> rep 11 19.000
7.4.2.2 双因素 ANOVA 分析
# 2x2: 独立变量: sex 独立变量: age 依赖变量: after
# 下面两种调用方式等价:
aov2 <- aov(after ~ sex * age, data = data)
aov2 <- aov(after ~ sex + age + sex:age, data = data)
summary(aov2)
#> Df Sum Sq Mean Sq F value Pr(>F)
#> sex 1 16.1 16.1 4.04 0.0550 .
#> age 1 39.0 39.0 9.79 0.0043 **
#> sex:age 1 89.6 89.6 22.51 6.6e-05 ***
#> Residuals 26 103.5 4.0
#> ---
#> Signif. codes:
#> 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# 显示均值
model.tables(aov2, "means")
#> Tables of means
#> Grand mean
#>
#> 6.483
#>
#> sex
#> F M
#> 7.445 5.926
#> rep 11.000 19.000
#>
#> age
#> old young
#> 7.874 5.556
#> rep 12.000 18.000
#>
#> sex:age
#> age
#> sex old young
#> F 6.260 8.433
#> rep 5.000 6.000
#> M 9.157 4.042
#> rep 7.000 12.000
7.4.2.3 Tukey HSD post-hoc 检验
TukeyHSD(aov2)
#> Tukey multiple comparisons of means
#> 95% family-wise confidence level
#>
#> Fit: aov(formula = after ~ sex + age + sex:age, data = data)
#>
#> $sex
#> diff lwr upr p adj
#> M-F -1.519 -3.073 0.03475 0.055
#>
#> $age
#> diff lwr upr p adj
#> young-old -2.318 -3.846 -0.7893 0.0044
#>
#> $`sex:age`
#> diff lwr upr p adj
#> M:old-F:old 2.8971 -0.308 6.1022 0.0870
#> F:young-F:old 2.1733 -1.141 5.4878 0.2966
#> M:young-F:old -2.2183 -5.132 0.6953 0.1833
#> F:young-M:old -0.7238 -3.769 2.3215 0.9139
#> M:young-M:old -5.1155 -7.719 -2.5122 0.0001
#> M:young-F:young -4.3917 -7.129 -1.6548 0.0009
7.4.3 有受试内变量的 ANOVAs
对于有受试内变量的 ANOVA 分析,数据必须满足为长格式。上面提到的数据都是宽格式,所以我们需要先转换数据格式(参见长宽格式互相转换)。
同样地,有受试内变量的 ANOVA 分析需要一个识别列。当前数据里是 subject
列。识别变量必须是一个因子,如果是数值类型,函数会解析错误导致不能正常工作。
library(tidyr)
# 原始数据 subject sex age before after 1 F old 9.5 7.1
# 2 M old 10.3 11.0 3 M old 7.5 5.8
# 转换为长格式
data_long <- gather(data, time, value, before:after)
# Look at first few rows
head(data_long)
#> subject sex age time value
#> 1 1 F old before 9.5
#> 2 2 M old before 10.3
#> 3 3 M old before 7.5
#> 4 4 F old before 12.4
#> 5 5 M old before 10.2
#> 6 6 M old before 11.0
# 确保subject列是一个因子
data_long$subject <- factor(data_long$subject)
7.4.3.1 单因素被试内 ANOVA
首先,像上面展示的一样将数据从宽格式转换到长格式并确保 subject
列是因子变量。如果 subject
是数值向量,而不是因子,结果将会出错。
# 独立变量 (被试内): time 依赖变量: value
aov_time <- aov(value ~ time + Error(subject/time), data = data_long)
summary(aov_time)
#>
#> Error: subject
#> Df Sum Sq Mean Sq F value Pr(>F)
#> Residuals 29 261 9.01
#>
#> Error: subject:time
#> Df Sum Sq Mean Sq F value Pr(>F)
#> time 1 155.5 155.5 71.4 2.6e-09 ***
#> Residuals 29 63.1 2.2
#> ---
#> Signif. codes:
#> 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# 因为一些原因,下面的代码不工作
model.tables(aov_time, "means")
#> Tables of means
#> Grand mean
#>
#> 8.093
#>
#> time
#> time
#> after before
#> 6.483 9.703
7.4.3.2 混合设计 ANOVA
首先,像上面展示的一样将数据从宽格式转换到长格式并确保 subject
列是因子变量。
# 2x2 mixed: 独立变量(被试间) : age 独立变量(被试内)
# : time 依赖变量: value
aov_age_time <- aov(value ~ age * time + Error(subject/time),
data = data_long)
summary(aov_age_time)
#>
#> Error: subject
#> Df Sum Sq Mean Sq F value Pr(>F)
#> age 1 24.4 24.44 2.89 0.1
#> Residuals 28 236.8 8.46
#>
#> Error: subject:time
#> Df Sum Sq Mean Sq F value Pr(>F)
#> time 1 155.5 155.5 98.1 1.2e-10 ***
#> age:time 1 18.8 18.8 11.8 0.0018 **
#> Residuals 28 44.4 1.6
#> ---
#> Signif. codes:
#> 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# 因为数据不平衡,下面代码不会工作
model.tables(aov_age_time, "means")
#> Tables of means
#> Grand mean
#>
#> 8.093
#>
#> age
#> old young
#> 8.875 7.572
#> rep 24.000 36.000
#>
#> time
#> after before
#> 6.483 9.703
#> rep 30.000 30.000
#>
#> age:time
#> time
#> age after before
#> old 7.950 9.800
#> rep 12.000 12.000
#> young 5.506 9.639
#> rep 18.000 18.000
7.4.3.3 更多被试内变量的 ANOVA
下面这些例子使用的不是上面的数据,但可以解释怎么进行相应的处理。首先,像上面展示的一样将数据从宽格式转换到长格式并确保 subject
列是因子变量。
# # 两个被试内变量 aov.ww <- aov(y ~ w1*w2 +
# Error(subject/(w1*w2)), data=data_long) #
# 1个被试间变量,两个被试内变量 aov.bww <- aov(y ~
# b1*w1*w2 + Error(subject/(w1*w2)) + b1,
# data=data_long) # 两个被试间变量,一个被试内变量
# aov.bww <- aov(y ~ b1*b2*w1 + Error(subject/(w1)) +
# b1*b2, data=data_long)