这个问题的答案在于 grid
和 gtable
包。图形中的所有内容都按照特定顺序排列,如果你仔细查找,就可以找到每个元素的位置。
library('gtable')
library('grid')
library('magrittr')
z <- ggplotGrob(p)
这个操作的最终目标是叠加顶部的 facet 标签,但是技巧在于这两个 facet 存在于同一行的网格空间中。它们是一个表格内的表格(查看名称为 "strip" 的行,还要注意 zeroGrob
;稍后这些将会有用):
z
...
...
如果您放大第一条带,您可以看到嵌套结构:
z$grob[[22]]
对于每个grob,我们都有一个对象来列出它绘制的顺序(
z),在网格中的位置(
cells),标签(
name)和几何形状(
grob)。
由于我们可以在gtable内创建gtable,因此我们将使用它来在原始图表上进行绘制。首先,我们需要找到需要替换的图表位置。
locations <- grep("strip-t", z$layout$name)
strip <- gtable_filter(z, "strip-t", trim = FALSE)
top <- strip$layout$t[1]
l <- strip$layout$l[c(1, 3)]
r <- strip$layout$r[c(2, 4)]
一旦我们有了位置,我们需要创建一个替换表。我们可以使用一个列表矩阵来完成这个任务(是的,很奇怪,但请接受它)。因为有两个方面和它们之间的间隙,所以在我们的情况下,这个矩阵需要有三列和两行。由于我们只是稍后要在矩阵中替换数据,所以我们将使用zeroGrob
创建一个矩阵:
mat <- matrix(vector("list", length = 6), nrow = 2)
mat[] <- list(zeroGrob())
res <- gtable_matrix("toprow", mat, unit(c(1, 0, 1), "null"), unit(c(1, 1), "null"))
这个口罩是分两步创建的,首先覆盖第一组面部特征,然后再覆盖第二组。在第一部分中,我们使用之前记录的位置来从原始图形中抓取适当的grob,并将其添加到我们的替换矩阵res
上,跨越整个长度。然后我们将该矩阵添加到我们的图形上方。
zz <- res %>%
gtable_add_grob(z$grobs[[locations[1]]]$grobs[[1]], 1, 1, 1, 3) %>%
gtable_add_grob(z, ., t = top, l = l[1], b = top, r = r[1], name = c("add-strip"))
pp <- gtable_add_grob(res, z$grobs[[locations[3]]]$grobs[[1]], 1, 1, 1, 3) %>%
gtable_add_grob(zz, ., t = top, l = l[2], b = top, r = r[2], name = c("add-strip"))
grid.newpage()
print(grid.draw(pp))
![Nested facet labels](https://istack.dev59.com/IeOPz.webp)
Error in do.call(unit.c, lapply(splitstrip, max_height)) : object 'unit.c' not found
该例子如下:ggplot(mpg, aes(x= cty, y = hwy)) + geom_point() + facet_nested(.~ manufacturer + model)
- jlpfacet_nested_wrap
的函数。如果这个函数不符合您的需求,我需要更多的细节信息。 - teunbrand