88-R可视化20-R的几种基于ggplot的拼图解决方案

2022-02-08 15:22:44 浏览数 (1)

  • Date : [[2022-01-06_Thu]]
  • Tags : #R/index/02 #R/R可视化 #R/R数据科学 #其他/答粉丝问题 #R/R包
  • 参考:
    • 05. R 的拼图方法 · 语雀 (yuque.com)[1]
    • (11条消息) 目前最全的R语言-图片的组合与拼接_R语言中文社区-CSDN博客[2]

前言

有的时候你可能想要把两个不同的图放在一起比较,亦或是想要实现文章中的这种排列:

那么拼图就显得尤为必要了。

1-几种主流方案

有几个经典流派的R包customLayout、grid、gridExtra、cowplot 等等。

但这里我并不介绍他们,而是哈德雷的patchwork 与Y 叔叔的aplot。

因为他们的语法实在太简单了。以至于我深陷其中,无法自拔。

2-patchwork

成功的让拼图变成了数学题。

拼图方式

两张图

图形的两两拼接,可以直接使用符号完成。

横向拼接

p1 | p2

代码语言:javascript复制
library(ggplot2)
library(patchwork)

p1 <- ggplot(mpg)   geom_point(aes(cty, hwy))
p2 <- ggplot(mpg)   geom_bar(aes(manufacturer))  
  coord_flip()
p1|p2

image.png

纵向拼接

p1 / p2

代码语言:javascript复制
library(ggplot2)
library(patchwork)

p1/p2

image.png

多张图

直接添加

类似两张图的添加方法,直接按照横向或纵向添加。

代码语言:javascript复制
library(ggplot2)
library(patchwork)

p3 <- ggplot(mpg)   geom_boxplot(aes(manufacturer, hwy))  
  facet_grid(year~.)  
  coord_flip()
p1 p2 p3

image.png

除此之外,如果横向添加四张图,patch 会自动调整图的位置。

代码语言:javascript复制
p4 <- ggplot(mpg)   
  geom_tile(aes(factor(cyl), drv, fill = stat(count)), stat = 'bin2d')
p1 p2 p3 p4

image.png

自定义添加位置
plot_layout()

plot_layout 函数类似地继承了矩阵与分面中的相关参数 ncol , nrowbyrow 。默认按行排列。

代码语言:javascript复制
p1 p2 p3 p4 plot_layout(byrow=F,nrow=2)

image.png

代码语言:javascript复制
p1 p2 p3 p4 plot_layout(nrow=4)

image.png

组合添加符号
代码语言:javascript复制
(p1|p2)/p3

利用 |/ 可以自定义水平或垂直布局。

设定design 参数

无需坐标与长宽设定的参数,也可以对布局进行设定。可以使用数字也可以使用英文字母。

代码语言:javascript复制
design <- "
  122
  1#3
  443
"
p1   p2   p3   p4 

我们可以把整个画板想象为一个3x3 的空间,其中各个数字表示对应的各个图像所在的位置,而 # 用来表示空白区域。

嵌套添加

通过嵌套,相当于将嵌套内的图形作为一个独立的子单元进行对应分割部分的处理。{}() 均可以达到嵌套效果。

代码语言:javascript复制
p1   {
  p2   {
    p3  
      p4  
      plot_layout(ncol = 1)
  }
}  
  plot_layout(ncol = 1)

image.png

添加空白空间

如果在添加图形时想要在图形间预留一些空白空间,可以使用 plot_spacer()

代码语言:javascript复制
p1 p2 plot_spacer() p3

image.png

调整拼接比例

参考:Wrap plots into a patchwork — wrap_plots • patchwork (data-imaginist.com)[3]

利用函数wrap_plots 相当于是patchwork 一般数学语法的进阶。

有多种参数:

这里仅仅介绍上下拼接时调整heights 参数。比如直接上下拼接,是没有占用空间大小之分的:

这时候如果借助wrap_plots 函数,就可以实现控制:

代码语言:javascript复制
wrap_plots(p1, p2, heights = c(11,1))

其接受一个向量,并按照输入的ggplot 对象顺序,分配大小。

如果是左右拼接,则可以通过widths 参数调整。

添加标记

整体标记

代码语言:javascript复制
layout <- "
  122
  1#3
  443
"
p1   p2   p3   p4   plot_layout(design = layout)   
  plot_annotation(title = 'mpg is so cool')

image.png

子图标记

也就是换个参数的是, tag_levels 会自动识别数字 1 , 字母A ,罗马数字 I 等。

代码语言:javascript复制
p1   p2   p3   p4   plot_annotation(tag_levels = 'A')

image.png

统一处理

当我们希望对全部图形进行处理但奈何单独对每个对象一一处理非常繁琐之时,可以利用 *& ,前者会为当前嵌套层的所有图像进行处理,而后者则会按照递归,处理所有的图层。

代码语言:javascript复制
(p1   p2   p3   p4) * theme_bw()

image.png

图例处理

设定 guides 参数。

代码语言:javascript复制
p1   p2   p3   p4   plot_layout(guides = 'collect')

对比一下之前

其他内容

直接添加

除了通过为创建的图形添加对象,通过对象调整图象位置,也可以通过ggplot 作图,直接添加。

代码语言:javascript复制
ggplot(mtcars)  
  geom_point(aes(mpg, disp))  
  ggplot(mtcars)   
  geom_boxplot(aes(gear, disp))

3-aplot

参见:R中的图片注释神包aplot - 简书 (jianshu.com)[4]

相比起patchwork 来说,aplot 就显得更加专注:适合那些主图 周围注释图的场景。

比如说这种热图的注释柱,就天然适合aplot 实现:

而且它的优点在于,长宽可以非常舒适的实现对其,比如之前patchwork 案例中提到的:

如果使用aplot:

代码语言:javascript复制
p1 %>% insert_bottom(p2, height = .1)

aplot 的使用也非常简单,也就是insert_*函数搭配管道符号。就不赘述了。

4-关于基础包

其实在 [[53-R可视化2-基础包绘图的入门功夫]] 我也提到过,可以通过声明mfcol 进行绘图内容在画布上的排列,具体可以参考:R-拼图系列-基础函数 - 简书 (jianshu.com)[5]

此外的话,customLayout 包也是支持base 语法的,你们也可以尝试一下哦。

今天,你学废了吗?

参考资料

[1]05. R 的拼图方法 · 语雀 (yuque.com): https://www.yuque.com/mugpeng/rr/mmfcvf

[2](11条消息) 目前最全的R语言-图片的组合与拼接_R语言中文社区-CSDN博客: https://blog.csdn.net/kMD8d5R/article/details/85182184

[3]Wrap plots into a patchwork — wrap_plots • patchwork (data-imaginist.com): https://patchwork.data-imaginist.com/reference/wrap_plots.html#:~:text=While the use of + is a natural,them into one composition, along with layout specifications.

[4]R中的图片注释神包aplot - 简书 (jianshu.com): https://www.jianshu.com/p/904166e52ea1

[5][53-R可视化2-基础包绘图的入门功夫]] 我也提到过,可以通过声明mfcol 进行绘图内容在画布上的排列,具体可以参考:[R-拼图系列-基础函数 - 简书 (jianshu.com): https://www.jianshu.com/p/a9c32dfff084

0 人点赞