Multi-figure panel
Objectives
-
Combine multiple plots into a single figure
-
Learn how to use
patchwork
andcowplot
The primary purpose of this lesson is to learn how to combine multiple figures into a single multi-panel figure using patchwork
and cowplot
. While we will learn how to customize and arrange plots in a multi-figure panel, this is not a comprehensive lesson on all aspects of patchwork
and cowplot
. If you have something specific in mind for your own data, I implore you to read the documentation for these packages to understand their full potential for customization.
Why do we need to learn to combine figures?
Combining multiple figures is advantageous when preparing results for conference presentations (via poster) or publication. Most journals place limits on the number of figures permitted per publication.
Example journals and their figure limits:
Journal | Impact Factor | Number of Figures |
---|---|---|
Nature Cancer | 60.72 | 5-8 |
Science | 47.73 | 6 |
Cancer Cell | 31.74 | 8 |
Journal of Clinical Oncology | 44.54 | 6 |
JAMA Oncology | 31.78 | 5 |
Cell Host and Microbe | 21.02 | 7 |
Load the libraries
There are multiple ways to combine figures using R. In this lesson, we will learn how to combine figures using two different R packages cowplot
and patchwork
, beginning with cowplot
.
To get started, load the libraries. Both packages are availabe for installation from CRAN using install.packages()
.
#Get patchwork
#To install use install.packages('patchwork')
#load
library(patchwork)
#Get cowplot
#To install use install.packages('cowplot')
#load
library(cowplot)
##
## Attaching package: 'cowplot'
## The following object is masked from 'package:patchwork':
##
## align_plots
#We will also use ggplot2
library(ggplot2)
The Data
This is the sixth lesson in our Data Visualization with R Series. At this point, we have created quite a few plots. For this lesson, we will focus on the RNA-Seq plots that we created in previous lessons. We will also include other related plots that were created using the same RNA-Seq data, but were not created throughout this course series. All plots were saved as R objects in .rds files. To load the data into R, we will need to use the readRDS()
function.
Let's load and view our plots. To view our plots, we can simply call the objects by name.
pca<-readRDS("./data/airwaypca.rds")
pca
volcano<-readRDS("./data/volcanoplot.rds")
volcano
## Warning: Using alpha for a discrete variable is not advised.
hmap<-readRDS("./data/airwayhm.rds")
hmap
sc<-readRDS("./data/stripchart.rds")
sc
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
The cowplot
documentation is very user friendly, so be sure to check it out. Some things you may want to look into further are the drawing functions, which allow you to easily integrate outside images onto your plots. Additionally, you may be interested in creating shared legends, which can be done using the get_legend()
function. Check out some examples here. Another CRAN package (ggpubr
), provides a wrapper function (See ggarrange()
) for cowplot's plot_grid()
that facilitates creating shared legends.
Using cowplot
to arrange figures
Let's start combining plots using the R package cowplot
. cowplot
is available on CRAN and can be installed using install.packages("cowplot")
.
The main function to combine figures using cowplot
is plot_grid()
. Let's check out the help documentation using ?plot_grid()
. The first and most important parameter is the list of plots we want to combine, plotlist
.
Let's check out its basic use by calling the plots we want to combine and providing labels using the labels
argument.
plot_grid(pca,volcano,hmap,sc, labels=LETTERS[1:4])
## Warning: Using alpha for a discrete variable is not advised.
I used the constant LETTERS
to subset the first four letters of the alphabet, but we could have also used c("A","B","C","D")
instead, or we could have set labels="AUTO"
to get the same result. There are quite a few parameters to adjust figure labels. To re-position labels, see label_x
, label_y
, hjust
, and vjust
. These each take either a single value to move all labels or a vector of values, one for each subplot. We can also change the size of the labels (label_size
), the font (label_fontface
), the label color (label_colour
), and the font type (label_fontfamily
).
Plot labels
Let's change various aspects of the plot labels.
plot_grid(pca,volcano,hmap,sc, labels=LETTERS[1:4],label_size = 14,
label_fontface = "bold.italic", label_colour ="blue",
label_fontfamily ="Times New Roman",
label_y=0.25)
## Warning: Using alpha for a discrete variable is not advised.
Here we changed the size of the labels to 14 pt and the color to blue. Also, the labels are now bold and italicized, and the font is Times New Roman.
Aligning plots
We can change the alignment of the plots by using the align
argument.
bc<-plot_grid(volcano,sc,labels = c("B","C"),align="h",axis="b")
## Warning: Using alpha for a discrete variable is not advised.
bc
Note: If you are using coord_equal()
or coord_fixed()
, it will be incredibly difficult to align plots using the align
parameter of plot_grid()
.
pca_vol_sc<-plot_grid((pca+theme(legend.position="right")),
bc,ncol=1,labels=c("A",""),align="v",axis="r",
label_x=0.25)
pca_vol_sc
Though we specified alignment parameters, "A" failed to align with "B" and "C". Unfortunately, there does not appear to be an easy fix. Note: the label_x
parameter was used to move the "A" label from the far left to the center.
Let's replace our coordinate system and look at the difference
pca1<-pca + theme(legend.position="right") + coord_cartesian()
## Coordinate system already present. Adding new coordinate system, which will replace the existing one.
plot_grid(pca1,bc,ncol=1,labels=c("A",""),align="v",axis="r")
We can fix our alignment issue by reverting back to the default coordinate system, but when we do, Figure A becomes misleading. Therefore, it is important that you pay attention to how combining figures alters the overall plot representation.
This is also an example of plot nesting. You can place the output of plot_grid()
within another plot_grid()
to create interesting plot arrangements.
Taking advantage of ggdraw
Let's draw an image on here, just to show that we can add one. There are two options. We can add an image as if it was another figure or we can simply draw it directly on our multi-figure panel. Let's do the latter since we have space, and adding the image will make figure A less awkward.
plos <- "./images/himesetal2014_plos.png" #save file path
a<-ggdraw() +
draw_image(plos,scale=1) # draw the image and save to object
p1<-plot_grid(NULL,a,NULL,(pca+theme(legend.position="right")),labels=c("","","A"),align="h",axis="b",nrow=1,rel_widths= c(0.05,0.75,0.1,1),label_x=1.1) #Add our new image to other
#bc is volcano plus strip chart
p2<-plot_grid(p1,NULL,bc,ncol=1,align="v",axis="l",rel_heights = c(1,0.1,1))
p3<-plot_grid(p2,NULL,hmap,ncol=1,labels=c("","","D"),align="v",axis="l",rel_heights=c(1,0.05,0.75))
p3
NULL
plots can be added to plot_grid()
to create extra space. Negative rel_heights
or rel_widths
can be used to subtract space.
We can also draw a label directly onto our multi-figure plot.
#Draw a label
labp<-ggdraw(p3)+
draw_label("Airway Data", color = "Black", size = 14, x=0.1,y=0.99,hjust=0.65,fontface="bold")
labp
Saving the plot
save_plot('airwayc_cplot.png',labp, base_asp=0.85,base_height=10.5,bg = "white")
The save_plot()
function by cowplot
is a bit more dynamic for multi-figure panels, but you may also use ggsave()
.
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 API that incites exploration and iteration, and scales to arbitrily complex layouts. ---Thomas Lin Pederson, Patchwork documentation.
Patchwork allows users to combine plots using simple mathematic operations such as +
and /
.
Combining two plots
Let's combine our PCA and volcano plots.
pca + volcano
## Warning: Using alpha for a discrete variable is not advised.
The last plot included in patchwork statements is considered the active plot, to which we can add additional ggplot2 layers. Notice the seemless alignment of these plots. Without any additional parameters, coord_fixed()
is maintained in the pca plot. patchwork
does a lot better with a fixed aspect plot.
Let's customize the legend position of the active plot.
pca + volcano +
theme(legend.position="right")
## Warning: Using alpha for a discrete variable is not advised.
We can easily add ggplot2 layers within our patchwork code.
We can continue to add plots using the +
symbol, and patchwork will try to form a grid, proceeding from left to right row-wise. Let's see this in action.
pca + volcano + hmap + sc
## Warning: Using alpha for a discrete variable is not advised.
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. Plotting layouts kind of follow the rules designated by the order of operations (Remember back to PEMDAS), the \
occurs before |
and +
.
#vertical stacking
pca / volcano
## Warning: Using alpha for a discrete variable is not advised.
#horizontal
pca | volcano
## Warning: Using alpha for a discrete variable is not advised.
#combining (pca and volcano stacked with a strip chart on the side)
pca | volcano / sc
## Warning: Using alpha for a discrete variable is not advised.
For specific layouts, it is a good idea to use parantheses for correct evaluation.
Compare the following:
pca | hmap / sc
((pca | hmap) / sc)
Using plot_layout()
The function plot_layout()
can be used to control the layout, combine legends, and overwrite plot titles.
pca1 <-pca + ggtitle("(A)")
pca1
sc1 <- sc + ggtitle("(B)")
sc1
#combine legends
pca1 + sc1 + plot_layout(ncol =1, guides = 'collect')
#Can control the relative heights and widths
pca1 + guides(shape = guide_legend(nrow=4)) + sc1 + plot_layout(nrow=1,guides = 'collect',widths=c(1.5,2))
Changing the relative sizes of the figures alters the alignment. Units may also be specified to control the height or width.
It is possible to design unique (non-grid) layouts using patchwork
, but it seems a bit more difficult than cowplot
in that regard.
Adding a spacer
We can add a spacer using plot_spacer()
to add blank sections to our plot. These blank sections are the size of our figure panels and may be different depending on how the plot is arranged.
(pca1 + guides(shape = guide_legend(nrow=4), color = guide_legend(nrow=2))) / plot_spacer() | sc1
Add our cowplot image
pca2<- pca + guides(shape = guide_legend(nrow=4))
(((a |pca2) / sc) / hmap) + plot_layout(guides='collect')
Including a title
To include a title, subtitle, or caption use the function plot_annotation()
.
(((a | pca2) / sc) / hmap) + plot_layout(guides='collect',heights=c(1,1,3)) +
plot_annotation(title = 'RNA-Seq Results', tag_levels = "A")
Notice that the assignment of "A" and "B" were automatic with the
tag_levels
parameter. The parentheses here are required.
Which package to use?
This is ultimately up to you. In general, patchwork
is easier to combine nicely aligned grid style plots. cowplot
seems to include greater opportunities for customization, but you could easily customize things like titles using ggplot2 layers with either package prior to combining figures. Both packages also allow you to inset figures and add non-ggplot2 figures.
Acknowledgements
Content in this tutorial was adapted from information in the cowplot documentation and patchwork documentation.