计算机@linux_python_R 技术帖

R绘图_ggpubr: Publication Ready Pl

2020-02-28  本文已影响0人  谢俊飞

Articles - ggpubr: Publication Ready Plots

作者: kassambara
日期:01/09/2017
翻译:谢俊飞

在同一页面上排列多个ggplot2图形,标准R函数 par()layout()并不能满足需求。
基本解决方案是使用gridExtra 包,该软件包具有以下功能:

但是,这些功能并不能对齐绘图面板 ; 取而代之的是,将图简单地按原样放置到网格中,因此轴并不能对齐。
如果需要进行轴对齐,则可以切换到Cowplot包,该程序包包含带有align参数的函数 plot_grid()。 但是,Cowplot包不包含任何用于多页布局的解决方案。 因此,我们提供了函数ggarrange() [ggpubr包],这是对plot_grid()函数的包装,可在多个页面上排列多个ggplots。 它还可以为多个图创建通用的唯一图例。

 #组织架构图
 R base package
        par()和 layout()
gridExtra package
        一页排图:grid.arrange()  和 arrangeGrob()
        多页排图:marrangeGrob()
Cowplot package
        轴对齐:plot_grid( align = " ")
ggpubr package
        多页布局:ggarrange()

本文将逐步向你展示如何使用以下R包(ggpubrcowplotgridExtra)中的帮助功能,在同一页面上以及在多个页面上组合多个ggplots图形。 我们还将介绍如何将已排列的图片导出到文件中。

准备工作

你需要安装R包ggpubr(版本> = 0.1.3),以轻松创建基于ggplot2的发布就绪图。
我们建议从GitHub安装最新的开发版本,如下所示:

if (!requireNamespace("BiocManager", quietly = TRUE))
    install.packages("BiocManager")
BiocManager::install("ggpubr")

请注意,安装ggpubr会自动安装gridExtracowplot软件包。 因此无需重新安装。

加载ggpubr

library(ggpubr)

数据: ToothGrowth 和 mtcars 数据集.

# ToothGrowth
data("ToothGrowth")
head(ToothGrowth)

# mtcars 
data("mtcars")
mtcars$name <- rownames(mtcars)
mtcars$cyl <- as.factor(mtcars$cyl)
head(mtcars[, c("name", "wt", "mpg", "cyl")])

绘制图片

在这里,我们将使用ggpubr中基于ggplot2的绘图功能。 你可以使用任何ggplot2函数来创建所需的绘图,以便以后进行排列。

我们先创建4个不同的图

# Box plot (bp)
bxp <- ggboxplot(ToothGrowth, x = "dose", y = "len",
                 color = "dose", palette = "jco") 
bxp
# Dot plot (dp)
dp <- ggdotplot(ToothGrowth, x = "dose", y = "len",
                color = "dose",palette = "jco", binwidth = 1)
dp
图片.png
# 条形图(bp)
bp <- ggbarplot(mtcars, x = "name", y = "mpg",
          fill = "cyl",               # 通过"cyl"更改填充颜色
          color = "white",            # 将栏边框颜色设置为白色
          palette = "jco",            #  jco颜色板. 查看 ?ggpar
          sort.val = "asc",           # 按升序排序
          sort.by.groups = TRUE,      # 每个组内排序
          x.text.angle = 90           #垂直旋转x轴文本
          )
bp + font("x.text", size = 8)
# 散点图 (sp)
sp <- ggscatter(mtcars, x = "wt", y = "mpg",
                add = "reg.line",               # 添加回归线
                conf.int = TRUE,                #添加置信区间
                color = "cyl", palette = "jco", # 按组"cyl"更改颜色
                shape = "cyl"                   # 按组"cyl"更改点的形状
                )+
  stat_cor(aes(color = cyl), label.x = 3)       # 添加相关系数
sp
图片.png

在一页上排列图片

要在一个页面上排列多个图片,我们将使用ggarrange()[在ggpubr中],它是对plot_grid()[在cowplot包中]函数的包装。 与标准函数plot_grid()相比,ggarange()可以在多个页面上排列多个图片。

ggarrange(bxp, dp, bp + rremove("x.text"), 
          labels = c("A", "B", "C"),
          ncol = 2, nrow = 2)
图片.png

另外,你也可以使用功能* plot_grid()* [cowplot包]:

library(cowplot)
plot_grid(bxp, dp, bp + rremove("x.text"), 
          labels = c("A", "B", "C"),
          ncol = 2, nrow = 2)

或者,函数grid.arrange() [gridExtra包]:

library("gridExtra")
grid.arrange(bxp, dp, bp + rremove("x.text"), 
             ncol = 2, nrow = 2)

注释排列的图形

R函数:annotate_figure() [ ggpubr包]

figure <- ggarrange(sp, bp + font("x.text", size = 10),
                    ncol = 1, nrow = 2)
annotate_figure(figure,
                top = text_grob("Visualizing mpg", color = "red", face = "bold", size = 14),
                bottom = text_grob("Data source: \n mtcars data set", color = "blue",
                                   hjust = 1, x = 1, face = "italic", size = 10),
                left = text_grob("Figure arranged using ggpubr", color = "green", rot = 90),
                right = "I'm done, thanks :-)!",
                fig.lab = "Figure 1", fig.lab.face = "bold"
                )
图片.png

注意,函数annotate_figure()支持任何ggplots。

对齐绘图面板

一个真实的例子是,例如,当绘制生存曲线并将风险表放置在主图下时。
为了说明这种情况,我们将使用survminer包。 首先,使用install.packages("survminer")安装,然后键入以下内容:

# 拟合生存曲线
library(survival)
fit <- survfit( Surv(time, status) ~ adhere, data = colon )
# 绘制生存曲线
library(survminer)
ggsurv <- ggsurvplot(fit, data = colon, 
                     palette = "jco",                              # jco颜色板
                     pval = TRUE, pval.coord = c(500, 0.4),        # 添加p值
                     risk.table = TRUE                             # 添加风险表
                     )
names(ggsurv)

ggsurv是一个包含以下组件的列表:

ggarrange(ggsurv$plot, ggsurv$table, heights = c(2, 0.7),
          ncol = 1, nrow = 2)
图片.png

可以看出,生存图和风险表的轴未垂直对齐。 要对齐它们,请指定参数align,如下所示。

ggarrange(ggsurv$plot, ggsurv$table, heights = c(2, 0.7),
          ncol = 1, nrow = 2, align = "v")
图片.png

更改图的列/行跨度

我们将使用嵌套的ggarrange()函数来更改图表的列/行跨度。
例如,使用下面的R代码:

ggarrange(sp,                                                 # 第一行散点图
          ggarrange(bxp, dp, ncol = 2, labels = c("B", "C")), # 第二行箱线图和点图
          nrow = 2, 
          labels = "A"                                        # 散点图的标签
          ) 
图片.png
ggdraw()

请注意,默认情况下,坐标从0到1,并且点(0,0)在画布的左下角(请参见下图)。


图片.png

draw_plot(). 将绘图放置在绘图画布上的某个位置:

draw_plot(plot, x = 0, y = 0, width = 1, height = 1)

draw_plot_label()。 在图的左上角添加图标签。 它可以处理带有关联坐标的标签向量。

draw_plot_label(label, x = 0, y = 1, size = 16, ...)
library("cowplot")
ggdraw() +
  draw_plot(bxp, x = 0, y = .5, width = .5, height = .5) +
  draw_plot(dp, x = .5, y = .5, width = .5, height = .5) +
  draw_plot(bp, x = 0, y = 0, width = 1, height = 0.5) +
  draw_plot_label(label = c("A", "B", "C"), size = 15,
                  x = c(0, 0.5, 0), y = c(1, 1, 0.5))
图片.png

rangingGrop() [gridExtra包]函数有助于更改绘图的行、列跨度。
例如,使用下面的代码:

library(gridExtra)
grid.arrange(sp,                             # 第一行,一个图跨越两列
             arrangeGrob(bxp, dp, ncol = 2), # 第二行,在2个不同的列中包含2个图
             nrow = 2)                       # 行数
图片.png

也可以在grid.arrange()函数中使用参数layout_matrix来创建复杂的布局。
在layout_matrix下面的R代码中,是2x2矩阵(2列2行)。 第一行全为1,这是第一幅图所在的地方,横跨两列; 第二行包含图2和3,各占据一列。

grid.arrange(bp,                                    # 条形图横跨两列
             bxp, sp,                               # 箱形图和散点图
             ncol = 2, nrow = 2, 
             layout_matrix = rbind(c(1,1), c(2,3)))
图片.png

请注意,也可以使用辅助函数draw_plot_label()[cowplot包]注释grid.arrange()函数的输出。

为了轻松注释grid.arrange()/ rangeGrob()输出(一个gtable),你应该首先使用函数as_ggplot()[ggpubr包]将其转换为ggplot。 接下来,你可以使用函数draw_plot_label()[在cowplot中]对其进行注释。

library("gridExtra")
library("cowplot")
# 使用arrangeGrob排列图片
# 返回gtable (gt)
gt <- arrangeGrob(bp,                               #条形图跨越两列
             bxp, sp,                               # 箱线图和散点图
             ncol = 2, nrow = 2, 
             layout_matrix = rbind(c(1,1), c(2,3)))
# Add labels to the arranged plots
p <- as_ggplot(gt) +                                     # 转换为ggplot
  draw_plot_label(label = c("A", "B", "C"), size = 15,
                  x = c(0, 0, 0.5), y = c(1, 0.5, 0.5))  # 添加标签
p
图片.png

在上面的R代码中,我们使用rangingGrob()代替了grid.arrange()
请注意,这两个函数之间的主要区别在于,grid.arrange()会自动输出排列图。
由于我们想在绘制图形之前对其进行注释,因此在这种情况下,最好使用函数arrangeGrob()

可以在grid.layout()函数的帮助下使用grid 包来创建复杂的布局。 它还提供了辅助函数viewport()来定义布局上的区域或视口。 函数print()用于将图放置在指定区域中。

不同的步骤可以总结如下:

  1. 创建图:p1,p2,p3,…
  2. 使用函数grid.newpage()移至网格设备上的新页面
  3. 创建一个布局2X2-列数= 2; 行数= 2
  4. 定义网格视口:图形设备上的矩形区域
  1. 将图打印到视口中
library(grid)
# 移至新页面
grid.newpage()
# 创建布局:nrow = 3,ncol = 2
pushViewport(viewport(layout = grid.layout(nrow = 3, ncol = 2)))
# 辅助功能,用于在布局上定义区域
define_region <- function(row, col){
  viewport(layout.pos.row = row, layout.pos.col = col)
} 
# 排列图片
print(sp, vp = define_region(row = 1, col = 1:2))   # 横跨两列
print(bxp, vp = define_region(row = 2, col = 1))
print(dp, vp = define_region(row = 2, col = 2))
print(bp + rremove("x.text"), vp = define_region(row = 3, col = 1:2))
图片.png

将通用图例用于组合的图.

将共用图例放在排列图的边缘,可以将ggarrange()[ggggbr包]与以下参数一起使用:

ggarrange(bxp, dp, labels = c("A", "B"),
          common.legend = TRUE, legend = "bottom")
图片.png

具有边际密度图的散点图

# 按组 ("Species")着色散点图
sp <- ggscatter(iris, x = "Sepal.Length", y = "Sepal.Width",
                color = "Species", palette = "jco",
                size = 3, alpha = 0.6)+
  border()                                         
# x(上图)和y(右图)的边际密度图
xplot <- ggdensity(iris, "Sepal.Length", fill = "Species",
                   palette = "jco")
yplot <- ggdensity(iris, "Sepal.Width", fill = "Species", 
                   palette = "jco")+
  rotate()
# 清理
yplot <- yplot + clean_theme() 
xplot <- xplot + clean_theme()
#排列图片
ggarrange(xplot, NULL, sp, yplot, 
          ncol = 2, nrow = 2,  align = "hv", 
          widths = c(2, 1), heights = c(1, 2),
          common.legend = TRUE)
图片.png

混排表格,文本和图片

在本部分中,我们将展示如何在图表旁边绘制表格和文本。 使用 iris数据集。我们首先创建以下图:

  1. 变量“ Sepal.Length”的密度图。 R函数:ggdensity()[ggpubr包]
  2. 摘要表,其中包含Sepal.Length的描述统计量(平均值,标准差,…)。
  1. 文字段落。 R函数:ggparagraph[ggpubr包]。
    我们使用函数ggarrang()[ggpubr包]来完成排列、组合三个图
# "Sepal.Length"密度图
#::::::::::::::::::::::::::::::::::::::
density.p <- ggdensity(iris, x = "Sepal.Length", 
                       fill = "Species", palette = "jco")
#绘制Sepal.Length汇总表
#::::::::::::::::::::::::::::::::::::::
# 按组计算描述性统计
stable <- desc_statby(iris, measure.var = "Sepal.Length",
                      grps = "Species")
stable <- stable[, c("Species", "length", "mean", "sd")]
# 汇总表图,主题中橙色
stable.p <- ggtexttable(stable, rows = NULL, 
                        theme = ttheme("mOrange"))
# 文本
#::::::::::::::::::::::::::::::::::::::
text <- paste("iris data set gives the measurements in cm",
              "of the variables sepal length and width",
              "and petal length and width, respectively,",
              "for 50 flowers from each of 3 species of iris.",
             "The species are Iris setosa, versicolor, and virginica.", sep = " ")
text.p <- ggparagraph(text = text, face = "italic", size = 11, color = "black")
#在同一页面上排列图
ggarrange(density.p, stable.p, text.p, 
          ncol = 1, nrow = 3,
          heights = c(1, 0.5, 0.3))
图片.png

在图片中插入图形元素

ggplot2中的*annotation_custom() *可用于在ggplot的绘图区域内添加表、图片或其他基于网格的元素。 格式为:

annotation_custom(grob, xmin, xmax, ymin, ymax)

我们将使用在上一节中创建的图表density.p和stable.p。

density.p + annotation_custom(ggplotGrob(stable.p),
                              xmin = 5.5, ymin = 0.7,
                              xmax = 8)
图片.png
  1. 使用iris数据集创建y ="Sepal.Width"和x ="Sepal.Length"的散点图。 R函数ggscatter()[ggpubr包]
  2. 分别创建具有透明背景的x和y变量的箱形图。 R函数:ggboxplot()[ggpubr]。
    将箱形图转换为在网格术语中称为“抓图”的图形对象。 R函数ggplotGrob()[ggplot2包]。
  3. 将箱形图样图块放入散点图内。 R函数:annotation_custom()[ggplot2包]。
    由于插入的箱线图与某些点重叠,因此箱线图使用透明背景。
# 按组("Species")着色散点图
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
sp <- ggscatter(iris, x = "Sepal.Length", y = "Sepal.Width",
                color = "Species", palette = "jco",
                size = 3, alpha = 0.6)
# 创建x / y变量的箱线图
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# x变量的箱线图
xbp <- ggboxplot(iris$Sepal.Length, width = 0.3, fill = "lightgray") +
  rotate() +
  theme_transparent()
# y变量的箱线图
ybp <- ggboxplot(iris$Sepal.Width, width = 0.3, fill = "lightgray") +
  theme_transparent()
# 创建外部图形对象
#在Grid中称为"grop"
xbp_grob <- ggplotGrob(xbp)
ybp_grob <- ggplotGrob(ybp)
# 将箱线图放置在散点图内
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
xmin <- min(iris$Sepal.Length); xmax <- max(iris$Sepal.Length)
ymin <- min(iris$Sepal.Width); ymax <- max(iris$Sepal.Width)
yoffset <- (1/15)*ymax; xoffset <- (1/15)*xmax
# 在散点图中插入xbp_grob
sp + annotation_custom(grob = xbp_grob, xmin = xmin, xmax = xmax, 
                       ymin = ymin-yoffset, ymax = ymin+yoffset) +
  # 在散点图中插入ybp_grob
  annotation_custom(grob = ybp_grob,
                       xmin = xmin-xoffset, xmax = xmin+xoffset, 
                       ymin = ymin, ymax = ymax)
图片.png

导入背景图像: 根据背景图像的格式,使用函数readJPEG()[jpeg包]或函数readPNG()[png包]。
为测试以下示例,请确保已安装png软件包。 您可以使用install.packages("png")命令进行安装。

# 导入图片
library(jpeg)
girl  <-  readJPEG("C:/Users/Administrator/Documents/jpeggirl01.jpg")

将ggplot与背景图像合并。 R函数:background_image()[ggpubr包]。

library(ggplot2)
library(ggpubr)
ggplot(iris, aes(Species, Sepal.Length))+
  background_image(girl)+
  geom_boxplot(aes(fill = Species), color = "white")+
  fill_palette("aaas")

通过指定参数alpha来更改箱线图填充颜色的透明度。 值应为[0,1],其中0为完全透明,1为不透明。

library(ggplot2)
library(ggpubr)
ggplot(iris, aes(Species, Sepal.Length))+
  background_image(img)+
  geom_boxplot(aes(fill = Species), color = "white", alpha = 0.5)+
  fill_palette("aaas")
Rplot03.png

另一个示例,覆盖了China地图和ggplot2:

china <- readJPEG("C:/Users/Administrator/Documents/china.jpg")
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width)) +
  background_image(china)+
  geom_point(aes(color = Species), alpha = 0.6, size = 5)+
  color_palette("jco")+
  theme(legend.position = "top")

多页排图

如果有一系列图片,比如20个,需要排列这些图并将它们放置在多页上。 每页有4个地块,则需要5页才能容纳20个图。
函数ggarrange()[ggpubr包]提供了一种方便的解决方案,可以在多个页面上排列多个ggplots。 在指定参数nrow和ncol之后,函数ggarrange()会自动计算保存绘图列表所需的页数。 它返回一个排列好的图片列表。
例如以下R代码:

multi.page <- ggarrange(bxp, dp, bp, sp,
                        nrow = 1, ncol = 2)

返回两页的列表,每页两个图。 你可以按如下所示可视化每个页面:

multi.page[[1]] # 查看第一页
multi.page[[2]] # 查看第二页

您还可以使用函数ggexport()[ggpubr]将排列好的图导出到pdf文件:

ggexport(multi.page, filename = "multi.page.ggplot2.pdf")

请注意,也可以使用功能marrangeGrob()[gridExtra包]创建多页输出。

library(gridExtra)
res <- marrangeGrob(list(bxp, dp, bp, sp), nrow = 1, ncol = 2)
# 到处为pdf文件
ggexport(res, filename = "multi.page.ggplot2.pdf")
# 交互式可视化
res

使用ggarrange()嵌套布局

我们将重新排列在(@ref(mix-table-text-and-ggplot)) 和 (@ref(create-some-plots))部分中创建的绘图。

p1 <- ggarrange(sp, bp + font("x.text", size = 9),
                ncol = 1, nrow = 2)
p2 <- ggarrange(density.p, stable.p, text.p, 
                ncol = 1, nrow = 3,
                heights = c(1, 0.5, 0.3))
ggarrange(p1, p2, ncol = 2, nrow = 1)
图片.png

导出图片

R函数:ggexport()[ggpubr包]。
首先,在iris数据集中创建与变量Sepal.Length,Sepal.Width,Petal.Length和Petal.Width对应的4个图片。

plots <- ggboxplot(iris, x = "Species",
                   y = c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width"),
                   color = "Species", palette = "jco"
                   )
plots[[1]]  # 打印第一张图
plots[[2]]  # 打印第二个图,依此类推...

接下来,您可以将单个图导出到文件(pdf,eps或png)(每页一个图)。 也可以每页2个排列的图片。

ggexport(plotlist = plots, filename = "test.pdf")

排列和导出。 在同一页面上指定nrow和ncol以展示多个图:

ggexport(plotlist = plots, filename = "test.pdf",
         nrow = 2, ncol = 1)

致谢

我们衷心感谢所有ggpubr依赖包的开发人员所做的努力:

上一篇下一篇

猜你喜欢

热点阅读