--- title: "Combining ggpubr Plots with patchwork" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Combining ggpubr Plots with patchwork} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} # Every plotting chunk needs patchwork; the correlation-matrix section also needs # ggcorrplot. Skip gracefully when a Suggests package is absent so the vignette # still builds under R CMD check's depends-only flavor. has_patchwork <- requireNamespace("patchwork", quietly = TRUE) has_ggcorrplot <- requireNamespace("ggcorrplot", quietly = TRUE) knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.width = 7, fig.height = 4.2, dpi = 96, message = FALSE, warning = FALSE, eval = has_patchwork ) ``` ```{r not-available, echo = FALSE, eval = !has_patchwork, results = "asis"} cat("> This vignette needs the **patchwork** package, which is not installed,", "so its output is not shown here.") ``` Every `ggpubr` function returns a standard `ggplot` object. That means you can lay several `ggpubr` plots out together with [patchwork](https://patchwork.data-imaginist.com/), whose `+`, `|` and `/` operators compose plots with almost no boilerplate. patchwork complements the built-in `ggpubr::ggarrange()`, and is handy when you want shared legends, nested layouts, or automatic panel tags. ```{r libs} library(ggpubr) library(patchwork) # A few publication-ready ggpubr plots to arrange data("ToothGrowth") tg <- ToothGrowth tg$dose <- as.factor(tg$dose) bxp <- ggboxplot(tg, x = "dose", y = "len", fill = "dose", palette = "jco", add = "jitter") + stat_compare_means(method = "anova") sctr <- ggscatter(mtcars, x = "wt", y = "mpg", add = "reg.line", conf.int = TRUE, cor.coef = TRUE, cor.method = "pearson") dens <- ggdensity(tg, x = "len", fill = "dose", palette = "jco") ``` ## Side by side, stacked, and nested Use `|` to place plots beside each other, `/` to stack them, and parentheses to nest layouts. ```{r side-by-side, fig.height = 3.6} bxp | sctr ``` ```{r nested, fig.height = 5.5} (bxp | sctr) / dens ``` ## Controlling the layout `plot_layout()` sets the number of columns/rows and the relative sizes. ```{r layout, fig.height = 3.6} (bxp | sctr) + plot_layout(widths = c(1, 1.4)) ``` ## One shared legend When panels carry the *same* legend, `plot_layout(guides = "collect")` gathers those identical legends into a single one. The `&` operator then applies a theme element to every panel at once - here to move the shared legend to the bottom. ```{r shared-legend, fig.height = 3.6} oj <- ggboxplot(subset(tg, supp == "OJ"), x = "dose", y = "len", fill = "dose", palette = "jco", add = "jitter") + labs(title = "Orange juice") vc <- ggboxplot(subset(tg, supp == "VC"), x = "dose", y = "len", fill = "dose", palette = "jco", add = "jitter") + labs(title = "Vitamin C") (oj | vc) + plot_layout(guides = "collect") & theme(legend.position = "bottom") ``` ## Titles and panel tags `plot_annotation()` adds a figure title and automatic panel tags (A, B, C ...), the layout most journals expect for a multi-panel figure. ```{r annotation, fig.height = 5.5} (bxp | sctr) / dens + plot_annotation( title = "Tooth growth and fuel economy", tag_levels = "A" ) ``` ## Correlation matrices `ggpubr` does not draw correlation matrices; for that, use [ggcorrplot](https://rpkgs.datanovia.com/ggcorrplot/), which also returns a `ggplot` and so composes with patchwork in exactly the same way. ```{r corr, eval = has_patchwork && has_ggcorrplot, fig.width = 8, fig.height = 4} library(ggcorrplot) corr <- round(cor(mtcars[, c("mpg", "disp", "hp", "drat", "wt", "qsec")]), 2) cmat <- ggcorrplot(corr, hc.order = TRUE, type = "lower", lab = TRUE, colors = c("#6D9EC1", "white", "#E46726")) cmat | sctr ``` ## See also - `ggpubr::ggarrange()` for the built-in arrangement helper. - [patchwork](https://patchwork.data-imaginist.com/) for the full composition API. - [ggcorrplot](https://rpkgs.datanovia.com/ggcorrplot/) for correlation matrices.