调整ggplot中facet_wrap的strip.text和strip.background大小一致

4

我想要制作许多"小图形"。

(背景说明) 我有太多的细节需要显示在单个图形中,因此我需要手动将它们分成单独的图形子集。我希望只需将所需的 ncolnrow 传递给 facet_wrap,它就会按需制作。但事实并非如此。

由于我的细节很多,空间很紧张。因此,我希望减小细节标签的大小。减小strip.text字体大小很容易,但不幸的是strip.background矩形不会随着字体大小而调整大小,也不提供大小参数(除了边框大小)。将其设置为element_blank()并不能真正删除为其预留的空间,只是使相同的空间透明。

最小化的工作例:

set.seed(1)
xcat = rep(1:10, 1000)
yvalue1 = rep(runif(10,5,7),1000)
yvalue2 = rep(runif(10,4,6),1000)
id = rep(1:1000,each=10)

df = data.frame(id,xcat,yvalue1,yvalue2)

for(i in seq(1, length(unique(df$id)), by=100)){
  print(
    ggplot(subset(df, id %in% unique(df$id)[i:(i+99)]), aes(x=xcat)) +
      annotate("line", y=yvalue1, x=xcat, colour="cornflowerblue") + 
      annotate("line", y=yvalue2, x=xcat, colour="grey20") + 
      theme(axis.text.x = element_text(size=5),
            axis.text.y = element_text(size=5),
            strip.text = element_text(size=5)) +
      facet_wrap(~id, ncol=10, nrow=10) + 
      expand_limits(y=0))
}
具有默认灰色条纹背景的示例图像 有什么想法可以减少该灰色条纹背景的高度,以便它不会占用太多空间?理想情况下,它的大小应与id文本的确切高度相同。
作为额外奖励,如何减少facets之间的间距?(在facet_wrap中是否有我错过的设置?)
在RStudio中使用 facet_wrap 渲染也需要很长时间(在没有facet_wrap的情况下速度更快)。
2个回答

3
您想要的结果可以通过修改ggplot创建的grobs来实现。这个过程有些麻烦,需要一些手动微调:
不考虑循环,我们可以从减少分面之间的间距开始。只需在theme中添加panel.spacing参数即可轻松完成。
library(ggplot2)

d <- ggplot(subset(df, id %in% unique(df$id)[1:(100)]), aes(x=xcat)) +
  annotate("line", y=yvalue1, x=xcat, colour="cornflowerblue") + 
  annotate("line", y=yvalue2, x=xcat, colour="grey20") + 
  theme(axis.text.x = element_text(size=5),
        axis.text.y = element_text(size=5),
        strip.text = element_text(size=5),
        panel.spacing = unit(.5, 'pt')) +
  facet_wrap(~id, ncol=10, nrow=10) +
  expand_limits(y=0)

我们需要生成一个ggplot2绘图grob。这将创建一个由组成绘图的单个元素列表。
g <- ggplotGrob(d)

head(g, 5)
# TableGrob (5 x 43) "layout": 13 grobs
#    z         cells        name                                    grob
# 1  3 ( 5- 5, 4- 4)  axis-t-1-1                          zeroGrob[NULL]
# 2  3 ( 5- 5, 8- 8)  axis-t-2-1                          zeroGrob[NULL]
# 3  3 ( 5- 5,12-12)  axis-t-3-1                          zeroGrob[NULL]
# 4  3 ( 5- 5,16-16)  axis-t-4-1                          zeroGrob[NULL]
# 5  3 ( 5- 5,20-20)  axis-t-5-1                          zeroGrob[NULL]
# 6  3 ( 5- 5,24-24)  axis-t-6-1                          zeroGrob[NULL]
# 7  3 ( 5- 5,28-28)  axis-t-7-1                          zeroGrob[NULL]
# 8  3 ( 5- 5,32-32)  axis-t-8-1                          zeroGrob[NULL]
# 9  3 ( 5- 5,36-36)  axis-t-9-1                          zeroGrob[NULL]
# 10 3 ( 5- 5,40-40) axis-t-10-1                          zeroGrob[NULL]
# 11 4 ( 4- 4, 4-40)      xlab-t                          zeroGrob[NULL]
# 12 8 ( 3- 3, 4-40)    subtitle zeroGrob[plot.subtitle..zeroGrob.77669]
# 13 9 ( 2- 2, 4-40)       title    zeroGrob[plot.title..zeroGrob.77668]

我们的目标是找到并修复相对于条带的高度。
for(i in 1:length(g$grobs)) {
  if(g$grobs[[i]]$name == 'strip') g$grobs[[i]]$heights <- unit(5, 'points')
}

很遗憾,strip grobs 也受到主图分割成不同 heights 的影响,因此我们还需要对它们进行调整。我没有找到一种程序化地识别哪些高度是指 strip 的方法,但检查 g$heights 可以比较快速地确定我们需要哪些。

g$heights
# [1] 5.5pt               0cm                 0cm                 0cm                 0cm                
# [6] 0.518897450532725cm 1null               0cm                 0.5pt               0cm                
# [11] 0.518897450532725cm 1null               0cm                 0.5pt               0cm                
# [16] 0.518897450532725cm 1null               0cm                 0.5pt               0cm                
# [21] 0.518897450532725cm 1null               0cm                 0.5pt               0cm                
# [26] 0.518897450532725cm 1null               0cm                 0.5pt               0cm                
# [31] 0.518897450532725cm 1null               0cm                 0.5pt               0cm                
# [36] 0.518897450532725cm 1null               0cm                 0.5pt               0cm                
# [41] 0.518897450532725cm 1null               0cm                 0.5pt               0cm                
# [46] 0.518897450532725cm 1null               0cm                 0.5pt               0cm                
# [51] 0.518897450532725cm 1null               0.306264269406393cm 1grobheight         0cm                
# [56] 5.5pt       

strip_grob_position <- seq(6, length(g$heights) - 5, 5)
for(i in strip_grob_position) {
  g$heights[[i]] = unit(.05, 'cm')
}

我们终于可以画出结果了:
library(grid)
grid.newpage()
grid.draw(g)

输入图像描述

我对这个主题一点也不精通,所以我的某些表述或解释可能是错误或不准确的。此外,可能有更好(更简单、更ggplot-ish)的方法来获得结果。


太棒了!我一直跟着做到最后。panel.spacingg$heights 只用于条带,这很有意义。但是,直到我绘制了中间结果并看到条带和绘图区之间的空间时,我才清楚你更改的最终高度是针对个别绘图区域的。您是如何选择0.05厘米作为适当的单位的? - Brian D
这只是一个看起来合理的值,困难的部分确实是找到正确的值。不确定为什么,但我无法从“cm”更改为任何其他单位,例如“pt”,因为通常情况下使用unit()函数可以更改单位。 - GGamba

3
根据Hadley的说法,现在有一个更简单的解决方案。我已经提供了一个使用更简单代码的示例,以便其他遇到此问题的人受益。关键是在设置文本大小时将margin = margin()。
set.seed(2112)
# dataframe with two groups
df <- data.frame(group1 = sample(LETTERS[1:5], size = 300, replace = TRUE),
    group2 = sample(1:5, size = 300, replace = TRUE),
    x = rnorm(300), y = rnorm(300))
ggplot(df, aes(x = x, y = y)) + 
    geom_point() + 
    facet_grid(group1 ~ group2) +
    theme(strip.text.x = element_text(size = 4, margin = margin()),
        strip.text.y = element_text(size = 20, margin = margin()))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接