听说你还不会画热图
群众纷纷表示图二是Excel画的,我觉得也是!Excel是生物学家的最爱啊。虽然做生信的人都看不上,最主要是没有记录,不具备可重复性。但现实就是大家都爱Excel。
如果我们在R里打命令fortunes::fortune(59)
,你将看到以下的输出:
Let’s not kid ourselves: the most widely used piece of software for statistics
is Excel.
— Brian D. Ripley (‘Statistical Methods Need Software: A View of Statistical Computing’)
Opening lecture RSS 2002, Plymouth (September 2002)
曾经有人问我,用R画热图怎么改颜色,我的回答是无能为力(没说怎么画,我怎么能够知道怎么改)。孔乙己老先生告诉我们回字有四样写法,而R画热图,岂止4种。基于base graphics有stats::heatmap
, gplots::heatmap.2
,以及多个包实现的heatmap.3
。交互式的热图有heatmaply
、d3heatmap
和iheatmapr
等包。
对于R代码无感的话,还有shinyheatmap
,直接提供交互式的网页操作界面。
基于grid graphics比较有名的有pheatmap
和ComplexHeatmap
包,要论复杂性,ComplexHeatmap
最厉害,要论简单而且也还比较漂亮,那就pheatmap
了。而且基于grid,也是保障了后续的操作,而且现在整个grid的生态最好,各种辅助的包太强大。
比如我这样画一个热图:
d = data.frame(matrix(rnorm(100), ncol=10))
colnames(d) = paste0('t', 1:10)
rownames(d) = paste0('g', 1:10)
library(pheatmap)
pheatmap(d) -> x
基本上我们发文章,图都是有多个panel拼起来的,这个pheatmap的输出,就可以用cowplot来拼,比如这里我用ggplot2画个散点图,然后拼在一起。
p = ggplot(d, aes(t1, t2)) + geom_point(size=5)
plot_grid(x$gtable, p, labels=c('A', 'B'))
就是这么简单,当然你还可以基于gtable进行操作,修改各种细节。
这里我不得不吐槽一下,很多人认为R有四套画图系统: base、grid、ggplot2、lattice。然后认为ggplot2最牛逼,天天ggplot2打遍天下无敌手一样,这就是没见过世面啊!(严格说lattice和ggplot2不能算图形系统)
试问ggplot2他爹是谁?ggplot2和lattice都是基于grid。现在我们ggplot2出图后各种高级玩法、以及我们自己写ggplot2图层,都是用grid!很多人认为cowplot是拼ggplot2的,plot_grid
这个函数名已经说明了一切,它是拼grid的,一切基于grid的图,比如上面的pheatmap
和ggplot2
,轻松拼在一起。
我能写出ggimage和ggtree包,能够一次解决ggplot2所有字体,都是因为懂一点grid。如果你对R语言的画图系统蒙圈的话,建议你读一下《树变图,图变树?》这一篇文章。
这里并没有否定ggplot2的意思,虽然grid更灵活,能做更多的事情,但ggplot2是我们的最爱,因为ggplot2所实现的语法,是人类友好的,让我们站在更高的角度,可以更加抽象地思考画图。但很多人不会用ggplot2画热图,因为ggplot2对tidy data的要求与热图的matrix是相悖的,我们可视化出来和matrix是对应的,但ggplot2要求我们把matrix,转化成长型的data.frame。虽然有很多热图的实现,但很多人还是想用ggplot2来出图,因为语法简单,用theme好操作细节。
这里简单介绍一下我很多年前写的一个简单的函数。在DOSE包里,我写了一个simplot
的函数,这个函数是基于ggplot2的,用于可视化DO语义相似性矩阵,像上面的数据,直接用simplot(d)
就可以出图:
默认会打印出数字,在矩阵比较小的时候,还是比较好的,如果你不想打印出来,可以用simplot(d, labs=F)
。
我们可以很容易地换配色方案,比如用类似于pheatmap的风格:
library(RColorBrewer)
colorRampPalette(rev(brewer.pal(n = 7,
name = "RdYlBu"))) -> cc
simplot(d) + scale_fill_gradientn(colors=cc(100))
再比如图例我们嫌太短了,想拉长一点:
simplot(d) +
scale_fill_gradientn(colors=cc(100)) +
theme(legend.key.height=unit(5, 'line'))
有了这个simplot函数,一键出图,然后再用ggplot2改细节,再也不要说不会用ggplot2画热图了。
Citation
G Yu, LG Wang, GR Yan, QY He. DOSE: an R/Bioconductor package for Disease Ontology Semantic and Enrichment analysis. Bioinformatics 2015, 31(4):608-609.