绘图有趣_手把手教你用R语言做科研绘图拼接!!!!!
写在前面后天就要回学校了,有点舍不得,舍不得家里2米的大床,舍不得我安静的书房,舍不得我专属的健身空间,舍不得一下楼就能吃到妈妈做的饭菜,舍不得老爸每周给我送水果熬的鸡汤鸽子汤,当然也舍不得家乡的朋友们。其实,还有一个舍不得的,就是家中的这一平方米。在家的7个多月时间里,有1/2的时间都是在这一平米度过,在这里处理了数据,完成了我真正意义上的第一篇英文paper和第一篇中文小论文,也自学...
写在前面
后天就要回学校了,有点舍不得,舍不得家里2米的大床,舍不得我安静的书房,舍不得我专属的健身空间,舍不得一下楼就能吃到妈妈做的饭菜,舍不得老爸每周给我送水果熬的鸡汤鸽子汤,当然也舍不得家乡的朋友们。
其实,还有一个舍不得的,就是家中的这一平方米。
在家的7个多月时间里,有1/2的时间都是在这一平米度过,在这里处理了数据,完成了我真正意义上的第一篇英文paper和第一篇中文小论文,也自学了许多有趣的知识,写了几篇阅读量还可以的推送。
所以,想在今天,临出发前,和大家,再分享一个有趣、简单但非常实用的小知识,我相信科研小白以及已经上路的研究生博士生们都会用到的。
毕竟回北京以后,我可能就又恢复到foodie美食博主的身份啦!
关于“绘图拼接”
“绘图拼接”,字面上的意思就是,把画好的一堆图,按照你想要的样式、结构,拼起来,成为一个大的、有更多信息和内容的图。
可能只是两个图简单的横向、纵向拼接。
也可能是多个类似主题图的拼接,且共用了一个legend。
也可能是两个复杂的图的拼接,每个复杂的图片里面还含有更多子图,reveal更多不同的信息。
那为何要掌握“绘图拼接”呢?因为大多数的期刊,在投稿的时候,都会在投稿须知里面说到,图片数量不允许超过多少多少,有的说不许超过5个,有的不许超过6个,也有可能是4个!
所以,如果把这些子图都分散开,那可能一个主题的图,就要占用4-6个图片数量了,无法表达论文的全部内容。
当然,也有人说,那就分开自己拼呗,Word里面手动拼!
是的,我曾经···也是这么干的··· 但是这个做法,实际上非常的不方便,每次调整图的时候都要手动调节位置就算了,关键有时间真的做不到“整整齐齐”!其实你们可以看到我的(b)和(d)图是有点歪的。
所以,如果以后想有进步,写出更好的论文,投更好的期刊,这种“手动拼接”做法是不建议的!
那如何解放双手,更简单的实现拼接呢?
先说说R中的par()和customLayout
其实之前,我也是用R写代码拼图的,但是只会简单的par(),比如par(mfrow(2,2)),创建一个2*2的画布,然后分别画四个子图。但是我发现,这种方法画的图①是不太美观②拼接的也不太智能(也可能我没深入挖掘这个方法),虽然它很实用,可以完美拼接R中的base绘图对象,但是我后来还是慢慢抛弃了他。
当然,customLayout也不错,听名字就知道很“自定义”和“为所欲为”,可以拼接base绘图对象也可以拼接ggplot2绘图对象。比如:
先创建一个叫lay1的画布,里面有四个子图空间(我这里没画具体的子图),宽比例是3:2(左:右),高比例是2:1(上:下)。
然后创建一个叫lay2的画布,同样是四个子空间,但是宽比例是3:5(左:右),高比例是2:4(上:下)。
然后就可以通过lay_bind_col()或者lay_bind_row()进行按列或者按行的拼接啦,比如我这里按列拼接两个画布。并且指定了lay1宽度是lay2宽度的三倍。
所以大家可以使用customLayout包尽情的customize!
学会用R中的cowplot和patchwork包
前面叽叽喳喳半天,终于到了本推送的核心内容了,其实我最想介绍的是cowplot和patchwork这两个包。
为何说这两个包呢?因为他的拼接思路更符合我们人脑画画的思路,step by step,且和ggplot2包的结合特别好。而ggplot2是R中最强大的绘图包,也是我最常用的,所以,我决定向大家推荐这二者!
首先要注意一下,cowplot包是可以直接install的,但是patchwork是要在github中加载的。如图所示。
把这两个包安装完之后,就可以进行拼接了。由于本推送的重点在“拼接”,而非“画图”,所以不会具体解释画图步骤,并且使用的也都是ggplot2中最常见的画图语法。
下面所有图的例子都来自R中内置数据库iris, mtcars和diamonds。
使用cowplot包进行拼接
大家可以发现,我们可以利用cowplot中的plot_grid()进行拼接,上下两幅图同样是纵向拼接,但是上面的图p5就拼接得整整齐齐,而下面图的Y轴并没有对齐。原因就是下面的图p6没有设置align="v",这里的“v”是vertical的意思。所以如果是水平对齐,就要设置align="h",以保证X轴水平对齐。
同样地,如果我想给拼接的两个图,添加标签,以及设置相对宽度,高度呢?
这里我做了水平拼接,设置了相对宽度是1:2,给两个图加了“A”和“B”标签。
是不是很方便很简单???
那如果有三个图呢?或者更多的图呢?
我们可以采取一个plot_grid()嵌套的方式来完成,比如下面这个图,我先plot_grid()对p7和p8完成拼接,并标记为“B”和“C”,然后再用这一个整体和p9进行拼接。
当然,我们还有一个画图思路,同样可以实现上面这个图的拼接,只不过是通过ggdraw()来完成的,而不是plot_grid()。
通过代码可以发现,这和我们小时候画画的思路是完全一样的!!!
先把p10和p11拼接起来,两个图的相对宽度是1:2,拼起来的图叫做p12。
然后开始拼接,先画一个空图ggdraw(),然后画图p9,后面四个数字x,y,z,w分别表示p9原点的相对坐标,和长宽占比,同理开始画p12,然后给p9和p12标签,并说明标签的位置和颜色。拼接出来如图所示。
当然,你也可以三个分别直接画上去,进行拼接。和上面对比一下代码、图,有没有看出啥区别!
当然,有人会说,有没有嵌套的拼接呢?
有的呀!
仔细看,这里是先ggdraw(p7),也就是说,先画好p7,然后后面的draw_plot(p8)的一系列操作就都是在p7画图基础上去完成啦!这样就实现了嵌套!
我相信有人会问,如何共用一个legend呢?
这里就有一个get_legend()的操作,也就是说我先保留了p10的图例,去掉了p11的图例,即theme(legend.position="none"),然后我获取p10的图例,然后通过plot_grid()对去掉图例的p10和本身没有图例的p11进行拼接,最后再进行一个复合拼接,将他们与图例拼在一起。
(下图只是一个我随便做的例子,图例对不上,重点看代码)
简单聊聊patchwork
其实能会使用cowplot()基本就可以完成我们正常的科研绘图和拼接工作了,但是为啥要聊聊patchwork呢?因为他的语法实在是太简单!太直观!太可爱啦!
它的表达方式有很多种,比如:加减乘除,比如交集并集,比如花括号,但是其拼接思路就和我们做加减乘除一样简单!
该图是由第一行代码画出来的
((p10+p11)+p7+p8+plot_layout(ncol=2))
大家可以自已试试其他两行代码,画出来有什么区别呢?自己动手加强理解!
至于最后图片的导出问题,比如如何导出高质量的图片,对dpi进行调整,请参考我之前写的“科研小白可能会遇到的期刊图片导出问题”。
写在最后
终于完成了在家的最后一篇推送,个人认为写的过程还是很开心、充实的,因为写推送与我而言,是爱好,也是利用输出方式巩固知识的一种方式。
为了写这篇推送我也把这些代码重复写了很多次,加深了理解,所以说practice makes perfect,希望能够对大家有所帮助吧!!!
欢迎大家阅读、转发、打赏、点赞一条龙呀~
更多推荐
所有评论(0)