使用替代函数再现 ggplot2 的 facet_wrap 图

Reproducing ggplot2's facet_wrap plot with alternative functions

我有一个 data.frame,我想用 ggplot2geom_bar 生成条形图,由 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))

很清楚如何使用 ggplot2facet_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")

但是由于post中没有提到的原因(不是很相关)facet_wrap对我不起作用,我需要求助于生成一个地块列表,每个地块一个集群,并自己将它们排列成网格:

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)
})

facet_wrap 有两个好处,我没有使用它而错过了它,我试图找出如何保留它:

  1. 自动决定网格布局的尺寸:知道 facet_wrap 是如何做到的,也许是否可以从 运行 上面使用 facet_wrap 命令的绘图中提取该信息?
  2. facet_wrap 也会自动共享轴标题和刻度,但 gridExtra::grid.arrangescater::multiplot 不会。使用这些函数实现这一点的唯一方法是为 lapply 调用中的所有集群抑制这些 themes,用户不想使用这些标签(模仿 facet_wrap) .我想问题 1 的答案提供了这个问题的答案(在所需网格中的集群位置上调节轴标签抑制),但如果有人有更直接的解决方案,那就太好了。

换句话说,我正在寻找一种通用的方法来使用上面的 facet_wrap 并应用 gridExtra::grid.arrangescater::multiplot (或任何其他函数)来重现绘图网格至 plot.list

facet_wrap 图的维度可以在 wrap_dims 函数中找到。

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))