大家是否还记得我写的文章《画个小圈圈 》?里面吐槽了ggpubr
这个包的存在是制造混乱,徒增学习成本 。我们知道ggplot2
包里有个qplot
函数,而在《ggplot2》的第一版中,hadley先用了一章介绍qplot
,再介绍grammar of graphics,然后这个qplot
就被吐槽,先入为主,给学习grammar of graphics,学习ggplot2语法制造了不必要的麻烦。然后如果你看《ggplot2》第二版,你就会发现qplot
这一章被删掉了。我说ggpubr
制造混乱,徒增学习成本 并不是为了吐槽某公众号,而是实事求是。
我并不反对封装,我并没有强迫症说大家一定要用ggplot2图形语法,而不能封装函数,我想我在《画个小圈圈 》已经说得很清楚了,封装画图的包,按我的观点是要么卖了数据处理的专业知识,要么卖了画图的专业知识。如果一个包做的封装太过于简单,像ggpubr
这种,数据必须是用户整理好的data.frame,而画图只是简单的两三个图层的叠加,那么当然可以减少你敲键盘输入,然而影响了初级用户学习ggplot2
,复杂的东西,我们当然想要用封装好的函数,等你自己啥都搞懂了,老板都要跟你掀桌子了。简单的东西也可以封装,减少输入嘛,只是特别不适用于ggplot2的图层,简单的设定你写个主题,我都举双手赞成,但两三个图层的简单拼凑我不支持,因为图层是积木,大家学习就是要对积木熟悉,然后才能搭出复杂的东西出来。特别简单的图层叠加正是你熟悉积木的时候,你不多敲点键盘,做为练习,又怎么能做出稍复杂点的东西呢?
我以下面这个ggpubr
的例子来讲一下吧。
set.seed(1234 ) df <- data.frame(="" sex="">'f' , 'M' ), each =200 )), weight=c(rnorm(200 , 55 ), rnorm(200 , 58 )))head (df)## sex weight ## 1 f 53.79293 ## 2 f 55.27743 ## 3 f 56.08444 ## 4 f 52.65430 ## 5 f 55.42912 ## 6 f 55.50606 ggdensity(df, x='weight' , add = 'mean' , rug = TRUE , color = 'sex' , fill = 'sex' , palette = c('#00AFBB' , '#E7B800' ))
这个图画density,就是geom_density
这个图层,下面加个指示位置的地毯线就是用geom_rug
:
require(ggplot2) p - ggplot (df , aes (weight , fill =sex, color =sex)) + geom_density (alpha =.5) + geom_rug ()print (p )
要加上分布的均值之类的统计量,还不容易,随手一算:
require(dplyr) df2 = group_by(df, sex) %>% summarize(m = mean(weight)) df2 ## # A tibble: 2 x 2 # # sex m # # # # 1 f 54.9 # # 2 M 58.1
然后再用geom_vline
加个线条,要搞颜色也是一样。
p + geom_vline(aes(xintercept=m , color=sex), df2, linetype='dashed' ) + scale_fill_manual(values =c('#00AFBB' , '#E7B800' )) + scale_color_manual(values =c('#00AFBB' , '#E7B800' ))
虽然你多输入了很多,但是在不断的输入中,你对各个图层更熟悉了,都是自由组合的组件。而且这还有个前提是ggplot2图层的文档很全,新手学习并不是很费力。所以我也不是说学习是最重要,如果费时费力,你又有产出的压力,比如老板叫你明天把结果放在他桌面上,学个鬼个!黄花菜都凉了。
ggpubr
另一方面是组间比较,这个跑个检验还不简单,要标显著嘛,我好多年前的文章《Useggplot2 》已经手把手教你们了,就不重复了。
我知道大家都喜欢少敲点代码,对ggpubr
的吐槽一是对学习有负面,二是不中用!今天跟大家一个中用的,比ggpubr
强N倍的包。
一键出图,但图不是简单拼图层能够拼出来的
附带做了统计,把统计量都给你在图上标准了
这有什么好处?画图+统计都要做,但一般我们开始只是在探索,而不是最终出要发表文章的图,而这个包,一画图就是图+统计,特别省事/省时间,等于说我毫不费力就可以试不同的图和统计检验。
场景1,你对这些是懂的,那么你不需要花时间去探索,这个包帮你做了。
场景2, 你对这些是不懂的,这是小白福音,你不懂你根本不知道要怎么做,甚至于不知道要做什么,你连学习的方向都没有,但人家帮你做了,你可以有目的性去学习相关的背景。
画图就是在感性(可视化)地探索数据,而统计检验给了你理性(定量)的指标。我们通常需要不断试,各种探索,最后可能都没用,或者有一种是最终要的,这个过程是很花时间的,而这个包,可以让你用很少的时间来探索一下。
ggstatsplot head (mtcars ) ## mpg cyl disp hp drat wt qsec vs am gear carb ## Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4 ## Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4 ## Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 ## Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1 ## Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2 ## Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
比如我想知道汽车的轮子数目和自动波/手波是否有关联,那么二联表走起,然后卡方检验,等你做完一小时过去了。而我用ggstatsplot
包,3秒钟搞定:
library(ggstatsplot) ggpiestats(data = mtcars, main = am, condition = cyl) + scale_fill_brewer(palette = 'Dark2' )
实际上你要做多少东西呢:
首先是二联表:
Contingency Tables ────────────────────────────── cyl 0 1 Total ────────────────────────────── 4 3 8 11 6 4 3 7 8 12 2 14 Total 19 13 32 ──────────────────────────────
再都卡方检验:
χ² Tests ────────────────────────────── Value df p ────────────────────────────── χ² 8.74 2 0.013 N 32 ──────────────────────────────
图上还有一些你可能不懂的东西,比如:
Nominal ──────────────────────────── Value ──────────────────────────── Phi-coefficient NaN Cramer's V 0.523 ────────────────────────────
省了多少时间?如果我只是看一看,最终这个结果我不要,那只花了3秒,如果这是我要的,我不懂卡方的情况下,也能做出来,那么我再有的放矢地去学习,甚至可以自己手工来一遍,这比毫无目的在各种手工学习或试错强太多,OK,我也懂用卡方的情况下,它做的东西,里面也可能有我不懂的东西,比如这个Cramer’s V,就打在图上,不懂,又可以去学习了,学习使我快乐,如果不是在图上看到,我不要说看不懂,根本都不知道有这东西的存在!所以不单单好用,也能让我们学到新东西。最重要的是老板说你先试一下,明天给我看个初步的结果,bingo,今晚可以愉快地睡觉!
组间比较 ggbetweenstats(data = iris, x = Species, y = Sepal.Length)
组间比较还有生物狗最喜欢的标注均值 ,不管是用点和/或数字都行。
相关性 ggscatterstats(data = iris, x = Sepal.Length, y = Petal.Length, title = 'Dataset: Iris flower data set' )
这里展示的只是最简单的,有很多参数,比如marginal.type = 'density'
那么marginal画出来的就不是histogram,而是density curve。也可以是boxplot哦。
相关性矩阵 ggcorrmat( data = subset(iris, Species == 'versicolor' ), cor.vars = c(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width))
分组做图并拼图 像上面的相关性矩阵,我只是切了versicolor一个物种来画,iris数据我们知道有三个物种,我们可以一个一个做,然后用cowplot
来拼图。
下面我先定义一个函数来画图:
plot_fun = function(data ) { ggscatterstats( data = data , x = Sepal.Length, y = Sepal.Width, marginal.type = 'boxplot' , title = glue::glue('Species: {(data$Species )} (n = {length(data$Sepal .Length)})' ) ) }
然后分组做图:
library(tidyr) library(purrr) nested_df <- iris="" %="">% group_by(Species) %>% nest() %>% mutate(p = map (data, plot_fun))
这样就有三张图,用cowplot
当然很容易拼,但我们经常需要拼完再加个title, 再底部加个注释什么的。你当然可以自己再画个tible什么的,然后再去拼。而ggstatsplot
直接封装了cowplot
,并提供了一些参数,让你加标题和注释什么的。比如上面画的三张图,我用combine_plots
拼出来:
combine_plots( plotlist = nested_df$p , labels = c('(a)' , '(b)' , '(c)' ), nrow = 3, ncol = 1, title.text = 'Relationship between sepal length and width for all Iris species' , title.size = 14, title.colour = 'blue' , caption.text = expression( paste( italic('Note' ), ': Iris flower dataset was collected by Edgar Anderson.' ), caption.size = 10 ) )
安装 安装要写到最后,因为我知道大家看到这里,才会急于想要来一波走你。目前此包还没在CRAN上,不过作者已经准备提交到,所以很快就会在CRAN上。给大家安装和升级带来便利。
目前可以通过github安装:
devtools::install_github('IndrajeetPatil/ggstatsplot' )