参考:R绘图系列-带有significant信息的boxplot | showteeth's blog[1]GitHub - const-ae/ggsignif: Easily add significance brackets to your ggplots[2][ggplot2添加p值和显著性 - 简书 (jianshu.com)](https://www.jianshu.com/p/77f12664540b "ggplot2添加p值和显著性 - 简书 (jianshu.com "ggplot2添加p值和显著性 - 简书 (jianshu.com)")")
之前提到过两个快速出图的R包:58-R可视化-7-用ggpubr与ggstatsplot快速出高颜值图 (qq.com)
通过看包说明不难发现,他们其实都调用了ggsignif:
通过这个包,我们就可以给自己创建的ggplot 绘图对象添加统计数据了。
简单学习一下ggsignif这个包:
这个包用起来非常简单,我们无须对数据框做任何处理,只需要在ggplot 的绘图代码基础上增加一些代码即可。
直接使用tidyverse 套件里的数据框iris:
> glimpse(iris)
Rows: 150
Columns: 5
$ Sepal.Length <dbl> 5.1, 4.9, 4.7, 4.6, 5.0, 5.4, 4.6, 5.0, 4.4, 4.9, 5.4, 4.8, 4.8, 4.3, 5.8, 5.7, 5.4, ~
$ Sepal.Width <dbl> 3.5, 3.0, 3.2, 3.1, 3.6, 3.9, 3.4, 3.4, 2.9, 3.1, 3.7, 3.4, 3.0, 3.0, 4.0, 4.4, 3.9, ~
$ Petal.Length <dbl> 1.4, 1.4, 1.3, 1.5, 1.4, 1.7, 1.4, 1.5, 1.4, 1.5, 1.5, 1.6, 1.4, 1.1, 1.2, 1.5, 1.3, ~
$ Petal.Width <dbl> 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.1, 0.2, 0.2, 0.1, 0.1, 0.2, 0.4, 0.4, ~
$ Species <fct> setosa, setosa, setosa, setosa, setosa, setosa, setosa, setosa, setosa, setosa, setos~
主要使用方法geom_signif:
ggplot(iris,aes(Species,Sepal.Length,fill=Species)) +
geom_boxplot()+geom_jitter(shape=16,size=2,position=position_jitter(0.2))+
geom_signif(comparisons = list(c("versicolor", "virginica"),
c("versicolor","setosa"),
c("virginica","setosa")),
map_signif_level=T,
textsize=6,test=wilcox.test,step_increase=0.2)+
guides(fill=FALSE)+xlab(NULL)+theme_classic()
这里我们通过comparisons 参数传入一个列表,列表中的元素为匹配给x 轴列中的分组信息。
这里我们需要手动指定。比如我们的数据有A,B,C 则需要列举两两间的所有可能。
有时候我们可能并不想要显著符号,而是需要具体的P值,可以设定map_signif_level 参数为F。
除此之外,test 参数默认为非参数方法的wilcox.test,如果我们的数据检验为正态,可以修改为t.test。
> tmp2 <- iris
> tmp2$norm.Length <- rnorm(150, 30, 4)
> shapiro.test(tmp2$norm.Length)
Shapiro-Wilk normality test
data: tmp2$norm.Length
W = 0.99252, p-value = 0.6236
验证正态分布后,使用t.test。ps:其实这里虽然数据本身是按照正态划分,但分组以后的数据呢?其实最好再对分组之后的每个数据做一个正态性检验。这里我只是举个例子,实际应用中参数方法还应考虑方差齐性等。比如正态方差非齐性的数据,一般还会选择Welch双样本t检验。
ggplot(iris,aes(Species,Sepal.Length,fill=Species)) +
geom_boxplot()+geom_jitter(shape=16,size=2,position=position_jitter(0.2))+
geom_signif(comparisons = list(c("versicolor", "virginica"),
c("versicolor","setosa"),
c("virginica","setosa")),
map_signif_level=F,
textsize=6,test=t.test,step_increase=0.2)+
guides(fill=FALSE)+xlab(NULL)+theme_classic()
ps:这里我觉得可以参考ggstatsplot 的方法,最好在图像中标记使用的是何种统计检验方法。不得不说,虽然审美层面我对其的一些做法并不认同,但可视化领域,它真的是老师般的存在。
主要使用方法stat_compare_means。如果需要检验两组以上数据是否存在差异,使用该方法。
和geom_signif 一样,stat_compare_means 也有参数 method 指定检验方法,非参数方法kruskal.test 与参数方法anova:
ggplot(iris,aes(Species,Sepal.Length,fill=Species)) +
geom_boxplot()+
# scale_fill_jco()+
geom_jitter(shape=16,size=2,position=position_jitter(0.2))+
stat_compare_means(method = "kruskal.test")+theme_bw()
# comparisons:需要进行统计检验的组别。
# step_increase:调整每个显著性标记之间的间隔。
# test:指定要使用的检验类型,默认是wilcox.test
# map_signif_level:是显示具体pvalue还是显示符号c("***"=0.001,"**"=0.01, "*"=0.05),可以自行指定符号。
# y_position:指定显著性标记的高度,如y_position=c(4,5,6)
# tip_length:设置横线两端向下生出的长度,如 tip_length = c(0)
# xmax, xmin: 标记棒的起始与终止位置
ggplot(iris,aes(Species,Sepal.Length,fill=Species)) +
geom_boxplot()+geom_jitter(shape=16,size=2,position=position_jitter(0.2))+
geom_signif(comparisons = list(c("versicolor", "virginica"),
c("versicolor","setosa"),
c("virginica","setosa")),
map_signif_level=c("@@@"=0.005,"@@"=0.01, "@"=0.1),
textsize=6,test=t.test,step_increase=0.2)
比如我们可以给图片进行分面,也会自动识别出分组并添加显著记录:
iris2 <- iris
iris2$facet_group <- sample(1:4, 150 ,replace = T)
my_comparisons <- list( c("setosa", "versicolor"),
c("setosa", "virginica"),
c("versicolor", "virginica") )
ggplot(iris2,aes(Species, Sepal.Length)) + geom_boxplot(aes(color = Species)) +
facet_grid(. ~facet_group) +
geom_signif(comparisons = my_comparisons,
map_signif_level=T,
textsize=6,test=wilcox.test,step_increase=0.2)
也就是开头这张图了:
虽然ggsignif可以帮助我们非常方便的标记显著,无论是分面显示,还是依赖comparisons 指定组别。
但如果我们希望对多个层面分组的数据进行比较呢?
这时候就需要我们手动标记了。
需要自己计算p 值并使用annotation 参数标记。
anno <- wilcox.test(iris2[iris2$facet_group == "3" & iris2$Species == "versicolor", "Sepal.Length"],
iris2[iris2$facet_group == "2" & iris2$Species == "virginica", "Sepal.Length"])$p.value
ggplot(iris2,aes(Species, Sepal.Length)) + geom_boxplot(aes(color = facet_group)) +
geom_signif(annotation=formatC(anno, digits=1),
y_position=8, xmin=2.05, xmax=2.9,
tip_length = c(0.2, 0.04))
其实这里直接用ggplot 图形函数annotate 也是差不多的。
关于annotations 参数的详细用法,可以参考:Chapter 5 How to Annotate a Graph Using GG Signif[3]
需要注意的是,ggplot 的映射是全局的,因此如果指定color 就会变成:
ggplot(iris2,aes(Species, Sepal.Length, color = facet_group)) + geom_boxplot() +
geom_signif(comparisons = my_comparisons,
map_signif_level=T,
textsize=6,test=wilcox.test,step_increase=0.2)
[1]R绘图系列-带有significant信息的boxplot | showteeth's blog: http://showteeth.tech/posts/40911.html
[2]GitHub - const-ae/ggsignif: Easily add significance brackets to your ggplots: https://github.com/const-ae/ggsignif
[3]Chapter 5 How to Annotate a Graph Using GG Signif: https://www.crumplab.com/psyc7709_2019/book/docs/how-to-annotate-a-graph-using-gg-signif.html