【发布时间】:2020-06-30 07:27:01
【问题描述】:
我正在尝试跨两个相邻面板组合小平面条(总是有两个相邻的具有相同的第一个 ID 变量,但有两种不同的场景,我们称它们为“A”和“B”)。我并不特别喜欢我尝试过的gtable + grid 解决方案,但遗憾的是我无法使用ggh4x 软件包中的facet_nested()(由于存在各种限制,我无法将它安装在我公司的服务器上和需要的依赖项 - 我只使用了相关代码,但由于依赖项,这又不容易)。
一个基本情节的最小可行示例,我希望通过组合顶部刻面条来指示哪些面板“属于一起”,使其更易于阅读,如下所示:
library(tidyverse)
library(gtable)
library(grid)
idx = 1:16
p1 = expand_grid(id=idx, id2=c("A", "B"), x=1:10) %>%
mutate(y=rnorm(n=n())) %>%
ggplot(aes(x=x,y=y)) +
geom_jitter() +
facet_wrap(~id + id2, nrow = 4, ncol=8)
带有“1”的条带、带有“2”的条带等应该合并(实际上它是一个稍长的文本,但这只是为了说明)。我试图为类似情况调整答案(https://stackoverflow.com/a/40316170/7744356 - 谢谢@markus 再次找到它),但这是我尝试过的。正如你在下面看到的,我产生的高度似乎是错误的。我认为这一定是我忽略/不理解的一些微不足道的事情。
# Combine strips for a ID
g <- ggplot_gtable(ggplot_build(p1))
strip <- gtable_filter(g, "strip-t", trim = FALSE)
stript <- which(grepl('strip-t', g$layout$name))
stript2 = stript[idx*2-1]
top <- strip$layout$t[idx*2-1]
# # Using the $b below instead of b = top[i]+1, also seems not to work
#bot <- strip$layout$b[idx*2-1]
l <- strip$layout$l[idx*2-1]
r <- strip$layout$r[idx*2]
mat <- matrix(vector("list",
length = length(idx)*3),
nrow = length(idx))
mat[] <- list(zeroGrob())
res <- gtable_matrix("toprow", mat,
unit(c(1, 0, 1), "null"),
unit( rep(1, length(idx)),
"null"))
for (i in 1:length(stript2)){
if (i==1){
zz <- res %>%
gtable_add_grob(g$grobs[[stript2[i]]]$grobs[[1]], 1, 1, 1, 3) %>%
gtable_add_grob(g, .,
t = top[i],
l = l[i],
b = top[i]+1,
r = r[i],
name = c("add-strip"))
} else {
zz <- res %>%
gtable_add_grob(g$grobs[[stript2[i]]]$grobs[[1]], 1, 1, 1, 3) %>%
gtable_add_grob(zz, .,
t = top[i],
l = l[i],
b = top[i]+1,
r = r[i],
name = c("add-strip"))
}
}
grid::grid.draw(zz)
------------ 使用 ggh4x 实现进行更新 -----
这可能会解决许多此类问题,但也有其缺点(例如,跨行的轴对齐有点手动,可能需要手动删除 x 轴并确保限制相同,添加统一的 y 轴标签,需要从 github 安装一个包:devtools::install_github("teunbrand/ggh4x@v0.1") 用于特定版本,另外,cowplot 与例如 ggtern 的交互很差)。所以我会喜欢它,如果有人仍然设法做一个纯粹的gtable + grid 版本。
library(tidyverse)
library(ggh4x)
library(cowplot)
plots = expand_grid(id=idx, id2=c("A", "B"), x=1:10) %>%
mutate(y=rnorm(n=n()),
plotrow=(id-1)%/%4+1) %>%
group_by(plotrow) %>%
group_map( ~ ggplot(data=.,
aes(x=x,y=y)) +
geom_jitter() +
facet_nested( ~ id + id2, ))
plot_grid(plotlist = plots, nrow = 4, ncol=1)
【问题讨论】:
-
@markus 谢谢! ZNK 对这个问题的回答正是我在这里尝试(但失败)适应的答案(而 teunbrand 使用 facet_nested 的第一个答案可以解决我的问题,但需要安装 ggh4x 包)。
-
@Björn 抱歉,这与您的问题无关,但您能告诉我这些依赖限制吗?我试图将 ggh4x 的导入限制为仅必需品,但 ggh4x 建议的软件包只能在使用它们的函数中调用,因此无需安装它们。回到您的问题,
facet_nested()的作用类似于facet_grid()而不是facet_wrap(),所以我认为这不会解决您的问题。 -
@teunbrand 这很尴尬。上次安装似乎出了点问题,但我使用
devtools::install_github("teunbrand/ggh4x@v0.1", force=T)重复了它(我使用版本 v0.1,因为我们的服务器上只有 ggplot2 v3.2.1 并且对用户可以安装的内容有很多限制 +要求用户检查他们安装的内容,所以我不涉及 tidyverse 升级),它运行良好。但是,正如你所说,我无法获得多行刻面条。我想我可以为每一行做一个单独的图,并将它们放在一起(例如使用拼凑)。 -
@Björn 是的,这似乎是一个合理的解决方案。感谢您对限制的解释,这对我很有帮助。我也考虑过制作一个
facet_wrap()版本,但是分面代码对编程来说太可怕了,所以我决定推迟它,直到有人开始要求它。无论如何,如果您无法安装新添加的内容,那也无法解决您的问题。
标签: r ggplot2 facet r-grid gtable