简体   繁体   中英

Reproducing ggplot2's facet_wrap plot with alternative functions

I have a data.frame that I'd like to produce bar plots for with ggplot2 's geom_bar , faceted by one of the columns in the data.frame - cluster :

library(dplyr)
df <- data.frame(cluster = c("c1","c1","c1","c2","c2","c2","c3","c3","c3"), group = rep(c("A","B","C"),3), p = c(0.4,0.2,0.4,0.5,0.5,0.5,0.2,0.3,0.5))

It's clear how to produce this with ggplot2 's facet_wrap :

library(ggplot2)
ggplot(df, aes(x = group, y = p, group = cluster, fill = group)) +
  geom_bar(stat = 'identity') +
  scale_x_discrete(name = NULL,labels = levels(df$group), breaks = sort(unique(df$group))) +
  facet_wrap(as.formula("~ cluster")) + theme_minimal() + theme(legend.title = element_blank()) + ylab("Fraction of cells")

But for reasons that are not mentioned in this post (not very relevant) facet_wrap doesn't work for me and I need to resort to producing a list of plots, one for each cluster, and arrange them myself in a grid:

plot.list <- lapply(unique(df$cluster),function(l){
  ggplot(dplyr::filter(df,cluster == l), aes(x = group, y = p, fill = group)) +
    geom_bar(stat = 'identity') +
    scale_x_discrete(name = NULL,labels = levels(dplyr::filter(df,cluster == l)$group), breaks = sort(unique(dplyr::filter(df,cluster == l)$group))) +
    theme_minimal() + theme(legend.title = element_blank(), plot.title = element_text(hjust = 0.5)) + ylab("Fraction of cells") + ggtitle(l)
})

There are two benefits of facet_wrap that I'm missing by not using it that I'm trying to find out how to retain:

  1. Automatically deciding on the dimensions of the grid layout: any idea how facet_wrap does that and perhaps if that information can be extracted from running the plotting that's using facet_wrap command above?
  2. facet_wrap also automatically shares the axis titles and ticks, but gridExtra::grid.arrange or scater::multiplot do not. The only way to achieve that with these functions is to suppress these themes for all the clusters in the lapply call which the user does not want to come out with these labels (imitating facet_wrap ). I guess that an answer for question 1 offers an answer to this question (conditioning axis label suppression on the location of the cluster in the desired grid), but if anyone has a more direct solution that'll be great.

In other and simple words, I'm looking for a generic way to reproduce the plot grid using facet_wrap above with gridExtra::grid.arrange or scater::multiplot (or any other function) applied to plot.list

The dimensions of the facet_wrap plot can be found in the wrap_dims function.

x=ggplot(df, aes(x = group, y = p, group = cluster, fill = group)) +
  geom_bar(stat = 'identity') +
  scale_x_discrete(name = NULL,labels = levels(df$group), breaks = sort(unique(df$group))) +
  facet_wrap(as.formula("~ cluster")) + theme_minimal() + theme(legend.title = element_blank()) + ylab("Fraction of cells")
col=wrap_dims(length(x))[2]

plot.list=list()
for (i in 1:length(unique(df$cluster))) {
  y=ggplot(dplyr::filter(df,cluster == unique(df$cluster)[i]), aes(x = group, y = p, fill = group)) +
    geom_bar(stat = 'identity') +
    scale_x_discrete(name = NULL,labels = levels(dplyr::filter(df,cluster == unique(df$cluster)[i])$group), breaks = sort(unique(dplyr::filter(df,cluster == unique(df$cluster)[i])$group))) +
    theme_minimal() + theme(plot.title = element_text(hjust = 0.5)) + ggtitle(unique(df$cluster)) + ylim(0, max(df$p))
  if (i<length(unique(df$cluster))) {
    y=y+theme(legend.position="none")
  }
  if (i>1) {
    y=y+ylab("")
  } else {
    y=y+ylab("Fraction of cells")
  }
  plot.list[[i]]=y
}
do.call(grid.arrange, c(plot.list, ncol=col))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM