技术贴:R语言拼图全面介绍

2022-03-29 11:25:29 浏览数 (1)

导语

GUIDE ╲

说起R语言的拼图,可能大家一点都不陌生,比如常用的“cowplot”和“patchwork”。gridExtra包也提供了一个拼图函数”grid.arrange“。另外,南方医科大学余光创教授也开发了一个更为神奇的拼图R包:aplot。本文将依次对它们的用法进行介绍。

准备工作

将cowplot、patchwork、gridExtra和aplot安装好即可。

代码语言:javascript复制
install.packages("cowplot")
install.packages("patchwork")
install.packages("gridExtra")
install.packages("aplot")

接下来依次讲解每个R包的用法:

拼图R包讲解

01

cowplot

cowplot是R语言中最常用的拼图软件之一。小编以它自带的例子进行介绍。

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

df <- data.frame(
  x = 1:10, y1 = 1:10, y2 = (1:10)^2, y3 = (1:10)^3, y4 = (1:10)^4
)

p1 <- ggplot(df, aes(x, y1))   geom_point()
p2 <- ggplot(df, aes(x, y2))   geom_point()
p3 <- ggplot(df, aes(x, y3))   geom_point()
p4 <- ggplot(df, aes(x, y4))   geom_point()
p5 <- ggplot(mpg, aes(as.factor(year), hwy))  
        geom_boxplot()  
        facet_wrap(~class, scales = "free_y")
        
plot_grid(p1, p2, p3, p4)

它可以对行数、列数以及子图的label进行设置。

代码语言:javascript复制
plot_grid(p1, p2, p3, ncol=3, labels=LETTERS[1:3])

并且可以对子图的宽度和高度进行调整,以实现更多复杂的布局。

代码语言:javascript复制
plot_grid(
  p1, p2, p3, p4,
  align = 'hv',
  rel_heights = c(2,1),
  rel_widths = c(1,2)
)
代码语言:javascript复制
plot_grid(
  p1, p5,
  align = "h", axis = "b", nrow = 1, rel_widths = c(1, 2)
)

02

patchwork

我的导师余光创教授曾写过一篇文章“cowplot乃旧爱,patchwork是新欢”来对patchwork进行介绍,大家可以在搜狗中点击微信搜索或者关注"YuLabSMU"公众号来查看这篇文章。它不但有着更为简洁易用的图形语法,很容易的实现众多复杂布局,还可以将多张子图的图例集中在一起,放到图的一侧。

代码语言:javascript复制
library(ggplot2)
p1 <- ggplot(mtcars)  
  geom_point(aes(mpg, disp))  
  ggtitle('图一')

p2 <- ggplot(mtcars)  
  geom_boxplot(aes(gear, disp, group = gear))  
  ggtitle('图二')

p3 <- ggplot(mtcars)  
  geom_point(aes(hp, wt, colour = mpg))  
  ggtitle('图三')

p4 <- ggplot(mtcars)  
  geom_bar(aes(gear))  
  facet_wrap(~cyl)  
  ggtitle('图四')
代码语言:javascript复制
layout <- c(
  area(t = 2, l = 1, b = 5, r = 4),
  area(t = 1, l = 3, b = 3, r = 5)
)
p1   p2  
  plot_layout(design = layout)
代码语言:javascript复制
g <- ggplot(mtcars)  
  geom_point(aes(mpg, disp, colour = mpg, size = wt))
g1 <- g   ggtitle("图一")
g2 <- g   scale_colour_viridis_c()   ggtitle("图二")

(p3 | (g1 / g2))  
  plot_layout(guides = 'collect')

03

gridExtra

gridExtra的一个经典用法是将散点图作为主图放在中心,展现二维属性,然后在X轴和Y轴处再分别做个副图,单独展现它们的一维属性。

代码语言:javascript复制
library(ggplot2)
empty <- ggplot()   geom_point(aes(1, 1), colour = "white")    
    theme(axis.ticks = element_blank(), 
        panel.background = element_blank(), 
        axis.line = element_blank(), 
        axis.text.x = element_blank(), axis.text.y = element_blank(), 
        axis.title.x = element_blank(), axis.title.y = element_blank())

p <- ggplot(mtcars, aes(mpg, disp))   geom_point()
p2 <- ggplot(mtcars, aes(mpg))   
  geom_density(fill='steelblue', alpha=.5)   
  ggtree::theme_dendrogram()
p3 <- ggplot(mtcars, aes(x=1, y=disp))   
  geom_boxplot(fill='firebrick', alpha=.5)   
  theme_void()
grid.arrange(empty,p2, p3, p, ncol = 2, nrow = 2,  
             widths = c(1, 4), heights = c(1, 4))

04

aplot

aplot是余教授开发的拼图R包,我们来用它重新画一下上面那幅图,这下子坐标终于能完美对上了。

代码语言:javascript复制
ap <- p %>% 
  insert_top(p2, height=.3) %>% 
  insert_left(p3, width=.1)

我们再来对比一下patchwork:

代码语言:javascript复制
library(ggtree)
set.seed(2020-03-27)
x <- rtree(10)
d <- data.frame(taxa=x$tip.label, value = abs(rnorm(10)))
p <- ggtree(x)   geom_tiplab(align = TRUE)   xlim(NA, 3)

library(ggstance)
p2 <- ggplot(d, aes(value, taxa))   geom_colh()   
  scale_x_continuous(expand=c(0,0))

library(patchwork)
p | p2

这张图乍一看还不错,似乎刻度线对齐的挺好,但仔细一看会发现进化树和条形图的y轴标签顺序都不对!那如果我们使用aplot来重新画这张图呢:

Y轴坐标终于能完美对齐了!这样更复杂一些的图形也可以轻松实现:

代码语言:javascript复制
library(readr)
library(tidyr)
library(dplyr)
library(ggplot2)
library(ggtree)

file <- system.file("extdata", "scRNA_dotplot_data.tsv.gz", package="aplot")
gene_cluster <- readr::read_tsv(file)

dot_plot <- gene_cluster %>% 
  mutate(`% Expressing` = (cell_exp_ct/cell_ct) * 100) %>% 
  filter(count > 0, `% Expressing` > 1) %>% 
  ggplot(aes(x=cluster, y = Gene, color = count, size = `% Expressing`))   
  geom_point()   
  cowplot::theme_cowplot()   
  theme(axis.line  = element_blank())  
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))  
  ylab(NULL)  
  theme(axis.ticks = element_blank())  
  scale_color_gradientn(colours = viridis::viridis(20), limits = c(0,4), oob = scales::squish, name = 'log2 (count   1)')  
  scale_y_discrete(position = "right")


mat <- gene_cluster %>% 
  select(-cell_ct, -cell_exp_ct, -Group) %>%  # drop unused columns to faciliate widening
  pivot_wider(names_from = cluster, values_from = count) %>% 
  data.frame() # make df as tibbles -> matrix annoying
row.names(mat) <- mat$Gene  # put gene in `row`
mat <- mat[,-1] #drop gene column as now in rows
clust <- hclust(dist(mat %>% as.matrix())) # hclust with distance matrix

ggtree_plot <- ggtree::ggtree(clust)

v_clust <- hclust(dist(mat %>% as.matrix() %>% t()))
ggtree_plot_col <- ggtree(v_clust)   layout_dendrogram()


labels= ggplot(gene_cluster, aes(cluster, y=1, fill=Group))   geom_tile()  
  scale_fill_brewer(palette = 'Set1',name="Cell Type")   
  theme_void() 
  
dot_plot %>% 
  insert_left(ggtree_plot, width=.2) %>%
  insert_top(labels, height=.02) %>%
  insert_top(ggtree_plot_col, height=.1)

小编总结

由于篇幅所限,这里无法将R语言拼图的所有特性讲解完全。谨希望通过这篇文章能让大家对拼图R包的应用有个较完整的了解,后续通过自己进一步学习可以掌握更多的拼图知识。

0 人点赞