Seurat is great for scRNAseq analysis and it provides many easy-to-use ggplot2 wrappers for visualization. However, this brings the cost of flexibility. For example, In FeaturePlot, one can specify multiple genes and also split.by to further split to multiple the conditions in the meta.data. If split.by is not NULL, the ncol is ignored so you can not arrange the grid.
This is best to understand with an example.
library(dplyr)
library(Seurat)
library(patchwork)
library(ggplot2)
# Load the PBMC dataset
pbmc.data <- Read10X(data.dir = "~/blog_data/filtered_gene_bc_matrices/hg19/")
# Initialize the Seurat object with the raw (non-normalized data).
pbmc <- CreateSeuratObject(counts = pbmc.data, project = "pbmc3k", min.cells = 3, min.features = 200)
## Warning: Feature names cannot have underscores ('_'), replacing with dashes
## ('-')
pbmc <- pbmc %>%
NormalizeData() %>%
FindVariableFeatures() %>%
ScaleData() %>%
RunPCA() %>%
RunUMAP(dims = 1:10)
## Warning: The default method for RunUMAP has changed from calling Python UMAP via reticulate to the R-native UWOT using the cosine metric
## To use Python UMAP via reticulate, set umap.method to 'umap-learn' and metric to 'correlation'
## This message will be shown once per session
add some dummy metadata
let’s pretend that the cells are from 5 different samples.
sample_names<- sample(paste0("sample", 1:5), size = ncol(pbmc), replace =TRUE)
pbmc$samples<- factor(sample_names)
pbmc@meta.data %>% head()
## orig.ident nCount_RNA nFeature_RNA samples
## AAACATACAACCAC pbmc3k 2419 779 sample5
## AAACATTGAGCTAC pbmc3k 4903 1352 sample4
## AAACATTGATCAGC pbmc3k 3147 1129 sample4
## AAACCGTGCTTCCG pbmc3k 2639 960 sample5
## AAACCGTGTATGCG pbmc3k 980 521 sample2
## AAACGCACTGGTAC pbmc3k 2163 781 sample1
table(pbmc@meta.data$samples)
##
## sample1 sample2 sample3 sample4 sample5
## 545 553 506 544 552
FeaturePlot(pbmc, features = "MS4A1", split.by = "samples")

You will have 5 UMAP showing in the same row and can not arrange to multiple rows.
I do not want to re-implement the FeaturePlot function but rather rearrange the ggplot2 output by patchwork.
I wrote the following function for this purpose.
Note, only a single gene can be specified. The idea is to generate a single UMAP plot for each sample and save them into a list and then arrange them by patchwork. Also make sure the metadata_column is a factor.
FeaturePlotSingle<- function(obj, feature, metadata_column, ...){
all_cells<- colnames(obj)
groups<- levels(obj@meta.data[, metadata_column])
# the minimal and maximal of the value to make the legend scale the same.
minimal<- min(obj[['RNA']]@data[feature, ])
maximal<- max(obj[['RNA']]@data[feature, ])
ps<- list()
for (group in groups) {
subset_indx<- obj@meta.data[, metadata_column] == group
subset_cells<- all_cells[subset_indx]
p<- FeaturePlot(obj, features = feature, cells= subset_cells, ...) +
scale_color_viridis_c(limits=c(minimal, maximal), direction = 1) +
ggtitle(group) +
theme(plot.title = element_text(size = 10, face = "bold"))
ps[[group]]<- p
}
return(ps)
}
Let’s test the function
p_list<- FeaturePlotSingle(pbmc, feature= "MS4A1", metadata_column = "samples", pt.size = 0.05, order =TRUE)
## Scale for 'colour' is already present. Adding another scale for 'colour',
## which will replace the existing scale.
## Scale for 'colour' is already present. Adding another scale for 'colour',
## which will replace the existing scale.
## Scale for 'colour' is already present. Adding another scale for 'colour',
## which will replace the existing scale.
## Scale for 'colour' is already present. Adding another scale for 'colour',
## which will replace the existing scale.
## Scale for 'colour' is already present. Adding another scale for 'colour',
## which will replace the existing scale.
layout1<-"
ABC
#DE
"
wrap_plots(p_list ,guides = 'collect', design = layout1)

You can do even better by moving the legend to the empty space!
## insert the legend space holder to the fourth
p_list2<- append(p_list, list(legend = guide_area()), 3)
layout2<-"
ABC
DEF
"
wrap_plots(p_list2, guides = 'collect', design = layout2)

patchwork is amazing and really flexible!