调整strip.background的大小以匹配ggplot中的strip.text facet_wrap

时间:2017-07-13 16:54:54

标签: r plot ggplot2 facet

我试图制作大量“小倍数”图。

(旁边/背景)我有太多方面要在单个图中显示,所以我需要手动将它们子集化为单独的图。我希望我可以将所需的ncolnrow传递给facet_wrap,它会尽可能多地传递给我。事实并非如此。

因为我有很多方面,所以空间非常宝贵。所以,我想减小刻面标签的大小。很容易减少strip.text字体大小,但遗憾的是strip.background矩形没有字体大小,也没有提供大小参数(除了边框大小)。将其设置为element_blank()实际上并没有删除为它预留的空间,它只是使相同的空间透明。

MWE:

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

example image with default grey strip.background

关于如何减少strip.background高度的任何想法,以免它占用太多空间?理想情况下,它的大小将与id文本的确切高度相匹配。

作为奖励,如何减少刻面之间的间距? (我缺少facet_wrap中的设置吗?)

使用facet_wrap在RStudio中渲染也需要很长时间(没有facet_wrap它会更快。

2 个答案:

答案 0 :(得分:2)

您希望的结果可以修改grobs创建的ggplot。这个过程有些混乱,需要进行一些手动微调:

抛开循环,这对问题没有影响,我们可以从减少方面之间的间距开始。通过将panel.spacing参数添加到theme来轻松完成。

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的影响,因此我们也必须减少那些。{1}} 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)

我们终于可以得出结果:

onbeforeunload

enter image description here

我在这个问题上根本不是专家,所以我可能错误地或不准确地说了或解释了什么。此外,可能有更好的(更简单和更ggplot-ish)方法来获得结果。

答案 1 :(得分:0)

根据Hadley,现在有一个更简单的解决方案,我提供了一个带有更简单代码的示例,以使任何其他人都upon绊绊地回答这个问题。关键是每当设置文本大小时都设置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()))