In this chapter, we will mainly focus on making a “publication-type” figure, with sub-plots and such using different tools in R. There are many different ways/packages to do this, but we will mainly focus on 2 packages: cowplot and ggpubr.

Now let us consider some of the plots we have made so far in the previous exercises. From the picture below, A and B are the figures that was made from the gene counts dataset and the figures C and D are using the Sepal.Length and Sepal.Width from the iris data. Now let us look into how we can combine each of the figures like it is shown here.

Now, let us go step by step. First let us make these plots into R objects. This will make things a lot easier.

p1 <- gc_long %>% 
  group_by(Time, Replicate) %>% 
  summarise(mean=mean(log10(count +1)),se=se(log10(count +1))) %>%
  ggplot(aes(x= Time, y= mean, fill = Replicate)) + 
  geom_col(position = position_dodge2()) +
  geom_errorbar(aes(ymin=mean-se, ymax=mean+se), position = position_dodge2(.9, padding = .6)) +
  ylab("mean(log10(count+1))") +
  theme(axis.ticks = element_blank()) +
  theme_bw(base_size = 10)

p2 <- ggplot(data = gc_long) +
  geom_boxplot(mapping = aes(x = Sample_Name, y = log10(count + 1), fill = Replicate)) +
  facet_grid(~Time , scales = "free", space = "free") +
  xlab("Time") +
  theme_bw(base_size = 10) +
  theme(axis.ticks.x = element_blank(), axis.text.x = element_blank())

p3 <- ggplot(data=iris,mapping=aes(x=Sepal.Length))+
  geom_density(aes(fill = Species), alpha = 0.6) +
  theme_light(base_size = 10)

p4 <- ggplot(data=iris,mapping=aes(x=Sepal.Length, y = Sepal.Width, color = Species)) +
  geom_point(size = 3, alpha = 0.6) +
  theme_light(base_size = 10)

The objects p1, p2, p3 and p4 as intuitively represent the plots A, B, C and D repectively.

1 Cowplot

1.1 plot_grid

One can use the simple plot_grid() function from the cowplot.

library(cowplot)
plot_grid(p1, p2)

plot

You can also do some simple customizations using nrow or ncol to specify the number of rows and columns and provide labels to those plots as well.

plot_grid(p1, p2, nrow = 2, labels = c("A", "B"))

plot

1.2 ggdraw and draw_plot

In cowplot, you can also customize the dimentions of the plots in a much more controlled fashion. For this one starts with ggdraw() which initiates the drawing “canvas” followed by draw_plot() that you use to draw the different plots on to the canvas.

Here is how the dimentions of the empty canvas looks like:

From here, you can draw your plots in the way you want using these dimensions. AN example is shown below, where we plot C and D similar to the plot above:

ggdraw() +
  draw_plot(p3, x = 0, y = 0, width = 1, height = .5) +
  draw_plot(p4, x = 0, y = .5, width = 1, height = .5) 

plot

You can also add “labels” to these figures using draw_plot_label() with the same dimensions.

ggdraw() +
  draw_plot(p3, x = 0, y = 0.5, width = 1, height = .5) +
  draw_plot(p4, x = 0, y = 0, width = 1, height = .5) +
  draw_plot_label(label = c("A", "B"), size = 15, x = c(0,0), y = c(1, 0.5))

plot

It is easier to draw three (or any odd number) plots in a neat way using this function compared to plot_grid()

ggdraw() +
  draw_plot(p3, x = 0, y = 0.5, width = 0.5, height = 0.5) +
  draw_plot(p4, x = 0.5, y = 0.5, width = 0.5, height = 0.5) +
  draw_plot(p2, 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))

plot

2 ggpubr

2.1 ggarrange

The package ggpubr comes with quite a few functions that can be very useful to make comprehensive figures. To start with the simple function, let’s start with ggarrange() that is used to put plots together.

library(ggpubr)
ggarrange(p3, p4, labels = c("A", "B"), nrow = 2)

plot

One of the nicer things with ggarrange() is that you can automatically have common legends that are shared between the figures.

ggarrange(p3, p4, labels = c("A", "B"), nrow = 2, common.legend = TRUE, legend = "right")

plot

2.2 Mixing text and table with Figures

You can include tables and even normal texts to any figure using ggtexttable() and ggparagraph(). Let us look into adding a table that we saw in the previous exercise with the gene counts dataset.

gc_table <- gc_long %>% 
  group_by(Time) %>% 
  summarise(mean=mean(log10(count +1)),se=se(log10(count +1)))

tab1 <- ggtexttable(gc_table, rows = NULL, 
                        theme = ttheme("mOrange"))
gc_text <- paste("In the experiment, RNA was extracted at four time points:", 
                 "before the gefinitib treatment (t=0), and two, six and twenty-four hours",
                 "after treatment (t=2, t=6, t=24, respectively).", sep = " ")

tex1 <- ggparagraph(text = gc_text, face = "italic", size = 11, color = "black")

Note   Here, for the text part, paste() has been used just to make it a bit easier to show here in the code. It could be used without the paste() command as well.

ggarrange(ggarrange(p1, p2, nrow = 2, labels = c("A", "B"), common.legend = TRUE, legend = "top"),
          ggarrange(tab1, tex1, nrow = 2),
          ncol = 2,
          widths = c(2, 1))

plot

2.3 Multiple-page

With ggarrange() it is also possible to make multiple-page plots. If you are for example making a report of many different figures this can come quite handy. Then you can use ggexport() to export these figures in a multi-page pdf.

multi.page <- ggarrange(p1, p2, p3, p4,
                        nrow = 1, ncol = 1)
ggexport(multi.page, filename = "multi.page.ggplot2.pdf")

Note   From this multi.page R object (which is of class list) , you can get the indivdual plots by multi.page[[1]], multi.page[[2]] and so on.

3 Exercise

Task   For the exercise in this session, let us look into way of using the tools available for combining plots to make one plot that could be very comprehensive. Try to code the figure below:

Tip: 1   Within ggarrange(), it is possible to adjust the dimension of each plot with widths and heights options.

Tip: 2   You can plot an empty plot with NULL.

4 Session info

sessionInfo()
## R version 4.1.2 (2021-11-01)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 18.04.6 LTS
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/openblas/libblas.so.3
## LAPACK: /usr/lib/x86_64-linux-gnu/libopenblasp-r0.2.20.so
## 
## locale:
##  [1] LC_CTYPE=C.UTF-8       LC_NUMERIC=C           LC_TIME=C.UTF-8       
##  [4] LC_COLLATE=C.UTF-8     LC_MONETARY=C.UTF-8    LC_MESSAGES=C.UTF-8   
##  [7] LC_PAPER=C.UTF-8       LC_NAME=C              LC_ADDRESS=C          
## [10] LC_TELEPHONE=C         LC_MEASUREMENT=C.UTF-8 LC_IDENTIFICATION=C   
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] ggpubr_0.4.0           cowplot_1.1.1          ggthemes_4.2.4        
##  [4] scales_1.1.1           ggrepel_0.9.1          wesanderson_0.3.6     
##  [7] forcats_0.5.1          stringr_1.4.0          purrr_0.3.4           
## [10] readr_2.1.1            tidyr_1.1.4            tibble_3.1.6          
## [13] tidyverse_1.3.1        reshape2_1.4.4         ggplot2_3.3.5         
## [16] formattable_0.2.1      kableExtra_1.3.4       dplyr_1.0.7           
## [19] lubridate_1.8.0        yaml_2.2.1             fontawesome_0.2.2.9000
## [22] captioner_2.2.3        bookdown_0.24          knitr_1.37            
## 
## loaded via a namespace (and not attached):
##  [1] nlme_3.1-153      fs_1.5.2          webshot_0.5.2     httr_1.4.2       
##  [5] tools_4.1.2       backports_1.4.1   bslib_0.3.1       utf8_1.2.2       
##  [9] R6_2.5.1          DBI_1.1.2         mgcv_1.8-38       colorspace_2.0-2 
## [13] withr_2.4.3       gridExtra_2.3     tidyselect_1.1.1  compiler_4.1.2   
## [17] cli_3.1.0         rvest_1.0.2       xml2_1.3.3        labeling_0.4.2   
## [21] sass_0.4.0        systemfonts_1.0.3 digest_0.6.29     rmarkdown_2.11   
## [25] svglite_2.0.0     pkgconfig_2.0.3   htmltools_0.5.2   dbplyr_2.1.1     
## [29] fastmap_1.1.0     highr_0.9         htmlwidgets_1.5.4 rlang_0.4.12     
## [33] readxl_1.3.1      rstudioapi_0.13   jquerylib_0.1.4   farver_2.1.0     
## [37] generics_0.1.1    jsonlite_1.7.3    car_3.0-12        magrittr_2.0.1   
## [41] Matrix_1.3-4      Rcpp_1.0.8        munsell_0.5.0     fansi_1.0.2      
## [45] abind_1.4-5       lifecycle_1.0.1   stringi_1.7.6     carData_3.0-5    
## [49] plyr_1.8.6        grid_4.1.2        crayon_1.4.2      lattice_0.20-45  
## [53] haven_2.4.3       splines_4.1.2     hms_1.1.1         pillar_1.6.4     
## [57] ggsignif_0.6.3    reprex_2.0.1      glue_1.6.0        evaluate_0.14    
## [61] modelr_0.1.8      vctrs_0.3.8       tzdb_0.2.0        cellranger_1.1.0 
## [65] gtable_0.3.0      assertthat_0.2.1  xfun_0.29         broom_0.7.11     
## [69] rstatix_0.7.0     viridisLite_0.4.0 ellipsis_0.3.2