Multi-figure panel
Introduction
The purpose of this lesson is combine multiple figures into a single
multi-panel figure using patchwork
or
cowplot
.
Why learn to combine figures?
Combining multiple figures is advantageous when preparing results for conference presentations (via poster) or publication. In addition, most scientific journals place limits on the number of figures permitted per publication, ranging from 3-7 figures typically.
Prepping the data
Before using patchwork
or cowplot
it
requires the objects to be saved as ggplot
object. Remember
to use as.ggplot
when required (ex. for pheatmap).
Load Libraries
library(patchwork)
library(cowplot)
library(ggplot2)
library(pheatmap)
library(dplyr)
library(tidyr)
library(pheatmap)
library(ggplotify)
At this point, we have created quite a few plots. These plots were
saved as R objects (.rds
). To load the data into R, we will
use the readRDS()
function.
#load the RDS
boxplots <- readRDS("boxplot_grid.RDS")
volcano <- readRDS("volcano.RDS")
gsea_plot1 <- readRDS("gsea_plot1.RDS")
gsea_plot2 <- readRDS("gsea_plot2.RDS")
pca <- readRDS("pca.RDS")
heatmap <- readRDS("heatmap.RDS")
cor_heatmap <- readRDS("cor_heatmap.RDS")
What is patchwork
?
The goal of patchwork is to make it ridiculously simple to combine
separate ggplots
into the same graphic. As such it tries to
solve the same problem as gridExtra::grid.arrange() and
cowplot::plot_grid
but using an application programming
interface (API) that incites exploration and iteration, and scales to
arbitrily complex layouts.
Place multiple plots in one grid
We can continue to add plots using the +
symbol, and
patchwork
will try to form a grid, proceeding from left to
right row-wise. But things get messy…
The plot layout can be controlled further with additional operators.
The |
symbol is used to place plots side by side, while the
/
symbol is used to stack plots vertically.
So for example using the |
parameter:
And for vertical layout we would use:
Adjust sizes of plots
Use of Nested Layouts
Now lets add row3 for our heatmap:
Now finally, lets add the GSEA plot 1 and 2 to row 3.
Not terrible, but we are seeing issues with sizing. Let’s try with cowplots.
What is cowplot
?
The
cowplot
package provides various features that help with creating publication-quality figures, such as a set of themes, functions to align plots and arrange them into complex compound figures, and functions that make it easy to annotate plots and or mix plots with images. The package was originally written for internal use in the Wilke lab, hence the name (Claus O. Wilke’s plot package). — cowplot 1.1.1
Cowplot also has some notable features including label customization, unique plot arrangements, and image drawing.
Using cowplot to arrange figures
The main function to combine figures is plot_grid()
.
Let’s check out the help documentation using
?plot_grid()
.
This figure isn’t bad already.
Go ahead and add the final row with the heatmap, gsea_plot1, and gsea_plot2. Label accordingly.
# FigEFG
FigEFG <- plot_grid(heatmap, gsea_plot1, gsea_plot2,
labels = c("E", "F", "G"),
nrow = 1)
FigEFG
Then move on to create the final figure.
# final figure
Final_figure <- plot_grid(FigABC, FigD, FigEFG, nrow = 3)
ggsave("Final_figure.pdf", height=6, width=8, dpi=300, units="in", scale = 2)
Session Info
## R version 4.4.3 (2025-02-28)
## Platform: x86_64-apple-darwin20
## Running under: macOS Sequoia 15.3
##
## Matrix products: default
## BLAS: /Library/Frameworks/R.framework/Versions/4.4-x86_64/Resources/lib/libRblas.0.dylib
## LAPACK: /Library/Frameworks/R.framework/Versions/4.4-x86_64/Resources/lib/libRlapack.dylib; LAPACK version 3.12.0
##
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
##
## time zone: America/New_York
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] ggplotify_0.1.2 tidyr_1.3.1 dplyr_1.1.4 pheatmap_1.0.12
## [5] ggplot2_3.5.2 cowplot_1.1.3 patchwork_1.3.0
##
## loaded via a namespace (and not attached):
## [1] tidyselect_1.2.1 farver_2.1.2 blob_1.2.4
## [4] R.utils_2.13.0 Biostrings_2.74.1 lazyeval_0.2.2
## [7] fastmap_1.2.0 digest_0.6.37 lifecycle_1.0.4
## [10] KEGGREST_1.46.0 tidytree_0.4.6 RSQLite_2.3.9
## [13] magrittr_2.0.3 compiler_4.4.3 rlang_1.1.6
## [16] sass_0.4.10 tools_4.4.3 igraph_2.1.4
## [19] yaml_2.3.10 ggtangle_0.0.6 data.table_1.17.0
## [22] knitr_1.50 labeling_0.4.3 bit_4.6.0
## [25] plyr_1.8.9 RColorBrewer_1.1-3 aplot_0.2.5
## [28] BiocParallel_1.40.2 withr_3.0.2 purrr_1.0.4
## [31] BiocGenerics_0.52.0 R.oo_1.27.0 grid_4.4.3
## [34] stats4_4.4.3 GOSemSim_2.32.0 enrichplot_1.26.6
## [37] colorspace_2.1-1 GO.db_3.20.0 scales_1.3.0
## [40] cli_3.6.4 rmarkdown_2.29 crayon_1.5.3
## [43] ragg_1.4.0 treeio_1.30.0 generics_0.1.3
## [46] ggtree_3.14.0 rstudioapi_0.17.1 httr_1.4.7
## [49] reshape2_1.4.4 ape_5.8-1 DBI_1.2.3
## [52] qvalue_2.38.0 cachem_1.1.0 DOSE_4.0.1
## [55] stringr_1.5.1 zlibbioc_1.52.0 splines_4.4.3
## [58] parallel_4.4.3 AnnotationDbi_1.68.0 XVector_0.46.0
## [61] rmdformats_1.0.4 yulab.utils_0.2.0 vctrs_0.6.5
## [64] Matrix_1.7-3 jsonlite_2.0.0 bookdown_0.42
## [67] gridGraphics_0.5-1 IRanges_2.40.1 S4Vectors_0.44.0
## [70] ggrepel_0.9.6 bit64_4.6.0-1 systemfonts_1.2.2
## [73] jquerylib_0.1.4 glue_1.8.0 codetools_0.2-20
## [76] stringi_1.8.7 gtable_0.3.6 GenomeInfoDb_1.42.3
## [79] UCSC.utils_1.2.0 munsell_0.5.1 tibble_3.2.1
## [82] pillar_1.10.2 htmltools_0.5.8.1 fgsea_1.32.0
## [85] GenomeInfoDbData_1.2.13 R6_2.6.1 textshaping_1.0.0
## [88] evaluate_1.0.3 Biobase_2.66.0 lattice_0.22-7
## [91] png_0.1-8 R.methodsS3_1.8.2 memoise_2.0.1
## [94] ggfun_0.1.8 bslib_0.9.0 Rcpp_1.0.14
## [97] fastmatch_1.1-6 nlme_3.1-168 xfun_0.52
## [100] fs_1.6.6 pkgconfig_2.0.3