答案在grid
和gtable
包内。情节中的一切都按特定的顺序排列,如果你挖一点,你可以找到所有的东西。
library('gtable')
library('grid')
library('magrittr') # for the %>% that I love so well
# First get the grob
z <- ggplotGrob(p)
这个操作的最终目标是覆盖在顶部面的标签,但诀窍是,这两个方面对格栅间距相同的行存在。他们是表内的表(看名称为“带”行,也注意到zeroGrob
的;这些都将是有益的更高版本):
z
## TableGrob (13 x 14) "layout": 34 grobs
## z cells name grob
## 1 0 (1-13, 1-14) background rect[plot.background..rect.522]
## 2 1 (7- 7, 4- 4) panel-1-1 gTree[panel-1.gTree.292]
...
## 20 3 (7- 7,12-12) axis-r-1 zeroGrob[NULL]
## 21 3 (9- 9,12-12) axis-r-2 zeroGrob[NULL]
## 22 2 (6- 6, 4- 4) strip-t-1 gtable[strip]
## 23 2 (6- 6, 6- 6) strip-t-2 gtable[strip]
## 24 2 (6- 6, 8- 8) strip-t-3 gtable[strip]
## 25 2 (6- 6,10-10) strip-t-4 gtable[strip]
## 26 2 (7- 7,11-11) strip-r-1 gtable[strip]
## 27 2 (9- 9,11-11) strip-r-2 gtable[strip]
...
## 32 8 (3- 3, 4-10) subtitle zeroGrob[plot.subtitle..zeroGrob.519]
## 33 9 (2- 2, 4-10) title zeroGrob[plot.title..zeroGrob.518]
## 34 10 (12-12, 4-10) caption zeroGrob[plot.caption..zeroGrob.520]
如果放大到第一条,你可以看到嵌套结构:
z$grob[[22]]
## TableGrob (2 x 1) "strip": 2 grobs
## z cells name grob
## 1 1 (1-1,1-1) strip absoluteGrob[strip.absoluteGrob.451]
## 2 2 (2-2,1-1) strip absoluteGrob[strip.absoluteGrob.475]
对于每个GROB,我们有一个对象,该目录(其中它的绘制顺序(ž),在网格中的位置(细胞),标签名称)和几何图形(grob)。
由于我们可以在gtables中创建gtables,我们将使用它来绘制我们的原始图。首先,我们需要找到需要替换的地块中的位置。
# Find the location of the strips in the main plot
locations <- grep("strip-t", z$layout$name)
# Filter out the strips (trim = FALSE is important here for positions relative to the main plot)
strip <- gtable_filter(z, "strip-t", trim = FALSE)
# Gathering our positions for the main plot
top <- strip$layout$t[1]
l <- strip$layout$l[c(1, 3)]
r <- strip$layout$r[c(2, 4)]
一旦我们有了职位,我们需要创建一个替换表。我们可以用列表矩阵来做到这一点(是的,这很奇怪,只是滚动它)。这个矩阵需要在我们的例子中有三列和两行,因为这两个方面和它们之间的差距。因为我们只是要在矩阵以后更换的数据,我们要创建一个与zeroGrob
S:分两步创建
mat <- matrix(vector("list", length = 6), nrow = 2)
mat[] <- list(zeroGrob())
# The separator for the facets has zero width
res <- gtable_matrix("toprow", mat, unit(c(1, 0, 1), "null"), unit(c(1, 1), "null"))
的面具,覆盖第一面组,然后第二个。在第一部分中,我们使用前面记录的位置从原始图中获取适当的grob,并将其添加到我们的替换矩阵res
的顶部,跨越整个长度。然后,我们将该矩阵添加到我们的图上。
# Adding the first layer
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"))
# Adding the second layer (note the indices)
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"))
# Plotting
grid.newpage()
print(grid.draw(pp))
非常感谢您的解决方案。我一直在努力研究如何推广这个解决方案来修改方面标签,如果它们出现在情节的右侧。你能说明一个人如何修改你的解决方案以适应布局基于plot函数'ggplot(cbind(df,df),aes(x = x,y = y))+ geom_point()+ facet_grid( f1 + f2〜f3)'?我还需要推广到一个案例,其中12个方面行减少到6个外部右侧标签,而不是4和2(因为我提供的重写函数会产生)。如果有帮助,很乐意提供一个清晰的例子。非常感谢! – nickb