2021-06-19 R语言执行单因素方差分析(单因素ANOVA)及多重比较

对于两组数据间的差异分析,最常见的方法就是使用T检验比较两组均值是否存在显著不同。当拓展到多组(三组及以上)时,使用T检验逐一两两比较的方法无疑是低效的,不仅仅由于需要的检验次数增多,而且发生I型错误(拒绝真)的概率也会增大。Fisher提出一种广义T检验的方法来比较三组及以上总体的均值,称为方差分析(ANOVA)。
几种常见的ANOVA包含单因素方差分析(单因素ANOVA)、单因素协方差分析(ANCOVA)、双因素方差分析(双因素ANOVA)、重复测量方差分析(重复测量ANOVA)、多元方差分析(MANOVA)等。本篇首先介绍其中最常涉及的单因素ANOVA在R语言中的实现过程,一组因子变量对应一组因变量

数据预处理

读入文件

#读入文件
soil <- read.table('soil.txt', sep = '\t', header = TRUE, stringsAsFactors = FALSE, check.names = FALSE)
group  <- read.table('group.txt', sep = '\t', header = TRUE, stringsAsFactors = FALSE, check.names = FALSE)
soil <- merge(soil, group, by = 'sample')
#假设样本采自三种土壤环境(A、B、C),我们比较三种土壤环境下的细菌群落的 chao1 指数是否存在显著差异
#以 chao1 指数为例,同时将分组列转换为因子变量
chao1 <- soil[ ,c('sample', 'site', 'chao1')]
chao1$site <- factor(chao1$site)
str(chao1)
head(chao1)
sample site    chao1
1   A1_1    A 2711.889
2   A1_2    A 3235.087
3   A1_3    A 3262.864
4   A2_1    A 3720.159
5   A2_2    A 3021.062
6   A2_3    A 3435.125

评估检验的假设条件

与T检验相似,ANOVA同样要求数据服从正态分布;此外,ANOVA还建立在各组方差相等的基础上。因此,在执行单因素ANOVA之前,我们首先应当对数据进行正态性分布验证,以及方差齐性检验。

正态性检验

#QQ-plot 检查数据是否符合正态分布(所有的点都离直线很近,落在置信区间内说明正态性良好)
library(car)
qqPlot(lm(chao1~site, data = chao1), simulate = TRUE, main = 'QQ Plot', labels = FALSE)
##Shapiro-Wilk 检验,当且仅当三者 p 值均大于 0.05 时表明数据符合正态分布,从中看出B组p值小于0.05,不符合正态分布(但是由于学术不精,暂且就当它符合正态分布吧)
shapiro <- tapply(chao1$chao1, chao1$site, shapiro.test)
shapiro
$A

    Shapiro-Wilk normality test

data:  X[[i]]
W = 0.96512, p-value = 0.8536


$B

    Shapiro-Wilk normality test

data:  X[[i]]
W = 0.83571, p-value = 0.02456


$C

    Shapiro-Wilk normality test

data:  X[[i]]
W = 0.91612, p-value = 0.2554

方差齐性检验

R语言中提供了一些可用来做方差齐性检验的函数,例如Bartlett检验(bartlett.test)、Fligner-Killeen检验(fligner.test())、Brown-Forsythe检验(HH包hov())等。
对于已经通过正态性检验的数据,推荐使用Bartlett检验来进行方差齐性检验(它建立在数据分布正态性的前提下,如果数据服从正态分布,这是最好的检验方法);Fligner-Killeen检验是一个非参数检验,通常在数据偏离正态性时使用(当然,如果数据已经偏离正态分布了,也没必要再继续了,所以Fligner-Killeen检验似乎并不能很好地适用在方差分析过程中)。

#使用 Bartlett 检验进行方差齐性检验(p 值大于 0.05 说明方差齐整)
bartlett.test(chao1~site, data = chao1)

    Bartlett test of homogeneity of variances

data:  chao1 by site
Bartlett's K-squared = 5.9425, df = 2, p-value = 0.05124

单因素方差分析

单因素ANOVA

我们的数据通过了正态性检验和方差齐性检验,接下来进行单因素ANOVA。R语言执行方差分析的命令是aov(),对于单因素方差分析,aov()函数书写为aov(y~A)的样式,A即为因子变量。
如果不满足上述前提假设,一是可以考虑转化数据(当然,我们需要确保转换后的数据能够被合理解释,否则将无意义),二是可以考虑使用非参数的检验方法,对于单因素的分析,可选的非参数替代方法例如Kruskal-Wallis检验(kruskal.test())、Friedman检验(friedman.test())等。

#满足假设,单因素方差分析,详情使用?aov查看帮助
fit <- aov(chao1~site, data = chao1)
 summary(fit)
            Df  Sum Sq Mean Sq F value   Pr(>F)    
site         2 4635658 2317829   17.48 6.66e-06 ***
Residuals   33 4376131  132610                     
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
#若想查看各组均值及标准差,可使用 aggregate()
chao1_mean <- aggregate(chao1$chao1, by = list(chao1$site), FUN = mean)
 Group.1        x
1       A 3340.115
2       B 2608.779
3       C 2552.170
chao1_sd <- aggregate(chao1$chao1, by = list(chao1$site), FUN = sd)
 Group.1        x
1       A 301.8213
2       B 497.8551
3       C 242.6404

多重比较

上述单因素ANOVA告诉我们3种土壤环境下的细菌群落的Chao1指数具有显著差异,这种差异是在整体水平而言的,并没有告诉我们究竟谁和谁存在差异。如果我们想继续获知两两分组之间的差异,进行多重比较即可。
常用Tukey HSD检验,在ANOVA结果的基础上继续执行事后两两比较。不推荐使用T检验(注意T检验和Tukey检验是两回事),原因正如本文开始时所提,多次T检验容易提高I型错误的概率。

##方差分析后,多重比较,继续探寻两两分组间的差异
#Tukey HSD 检验
tuk <- TukeyHSD(fit, conf.level = 0.95)
plot(tuk)
tuk
  Tukey multiple comparisons of means
    95% family-wise confidence level

Fit: aov(formula = chao1 ~ site, data = chao1)

$site
          diff        lwr       upr     p adj
B-A -731.33642 -1096.1330 -366.5398 0.0000681
C-A -787.94475 -1152.7413 -423.1482 0.0000223
C-B  -56.60833  -421.4049  308.1882 0.9233767

显著水平默认为0.05。Tukey检验显示,A组和B组、A组和C组存在显著差异,但B组和C组无差异。(根据文字部分p值判断;或者根据图片判断,未越过虚线则表示无差异)

multcomp包中提供了更直观的方法,展示Tukey检验的结果。
library(multcomp)
tuk <- glht(fit, alternative = 'two.sided', linfct = mcp(site = 'Tukey'))
plot(cld(tuk, level = 0.05, decreasing = TRUE))

同样地,显著水平默认为0.05。结果以箱线图的方式,直观地为我们展示出组间差异。从图中我们可以轻易得知,A组(A环境下的土壤细菌群落)的Chao1指数显著高于其它两组(B、C环境下的土壤细菌群落),同时B、C二者无差异。

ggplot2柱状图示例

dat <- merge(chao1_mean, chao1_sd, by = 'Group.1')
names(dat) <- c('group', 'mean', 'sd')
dat <- cbind(dat, sign = c('a', 'b', 'b'))

library(ggplot2)

ggplot(dat, aes(group, mean)) +
geom_col(aes(fill = group), width = 0.4, show.legend = FALSE) +
geom_errorbar(aes(ymax = mean + sd, ymin = mean - sd), width = 0.15, size = 0.5) +
geom_text(aes(label = sign, y = mean +sd + 200)) +
theme(panel.grid = element_blank(), panel.background = element_rect(color = 'black', fill = 'transparent'), plot.title = element_text(hjust = 0.5)) +
labs(x = 'Group', y = 'Chao1', title = 'Tukey HSD test')

来源:小白鱼的生统笔记
总代码

##单因素方差分析(单因素 ANOVA)

#读入文件
soil <- read.table('soil.txt', sep = '\t', header = TRUE, stringsAsFactors = FALSE, check.names = FALSE)
group  <- read.table('group.txt', sep = '\t', header = TRUE, stringsAsFactors = FALSE, check.names = FALSE)
soil <- merge(soil, group, by = 'sample')

#假设样本采自三种土壤环境(A、B、C),我们比较三种土壤环境下的细菌群落的 chao1 指数是否存在显著差异
#以 chao1 指数为例,同时将分组列转换为因子变量
chao1 <- soil[ ,c('sample', 'site', 'chao1')]
chao1$site <- factor(chao1$site)
str(chao1)
head(chao1)

#QQ-plot 检查数据是否符合正态分布(所有的点都离直线很近,落在置信区间内说明正态性良好)
library(car)
qqPlot(lm(chao1~site, data = chao1), simulate = TRUE, main = 'QQ Plot', labels = FALSE)


##Shapiro-Wilk 检验,当且仅当两者 p 值均大于 0.05 时表明数据符合正态分布
shapiro <- tapply(chao1$chao1, chao1$site, shapiro.test)
shapiro

#使用 Bartlett 检验进行方差齐性检验(p 值大于 0.05 说明方差齐整)
bartlett.test(chao1~site, data = chao1)

#满足假设,单因素方差分析,详情使用?aov查看帮助
fit <- aov(chao1~site, data = chao1)
summary(fit)

#不满足假设,可使用非参数方法,例如 Kruskal-Wallis Test、Friedman Test
#kruskal.test()、friedman.test()

#若想查看各组均值及标准差,可使用 aggregate()
chao1_mean <- aggregate(chao1$chao1, by = list(chao1$site), FUN = mean)
chao1_sd <- aggregate(chao1$chao1, by = list(chao1$site), FUN = sd)

##方差分析后,多重比较,继续探寻两两分组间的差异
#Tukey HSD 检验
tuk <- TukeyHSD(fit, conf.level = 0.95)
plot(tuk)
tuk

#或者更直观地展示 Tukey HSD 检验结果
library(multcomp)
tuk <- glht(fit, alternative = 'two.sided', linfct = mcp(site = 'Tukey'))
plot(cld(tuk, level = 0.05, decreasing = TRUE))

#不妨自己作个图展示下(ggplot2 柱状图示例)
dat <- merge(chao1_mean, chao1_sd, by = 'Group.1')
names(dat) <- c('group', 'mean', 'sd')
dat <- cbind(dat, sign = c('a', 'b', 'b'))

library(ggplot2)

ggplot(dat, aes(group, mean)) +
geom_col(aes(fill = group), width = 0.4, show.legend = FALSE) +
geom_errorbar(aes(ymax = mean + sd, ymin = mean - sd), width = 0.15, size = 0.5) +
geom_text(aes(label = sign, y = mean +sd + 200)) +
theme(panel.grid = element_blank(), panel.background = element_rect(color = 'black', fill = 'transparent'), plot.title = element_text(hjust = 0.5)) +
labs(x = 'Group', y = 'Chao1', title = 'Tukey HSD test')
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335