【问题标题】:how to reduce vertical spacing between facet labels when using facet_wrap?使用 facet_wrap 时如何减少构面标签之间的垂直间距?
【发布时间】:2016-12-24 08:57:46
【问题描述】:

我使用 facet_wrap 绘制了按两个因素分组的二维面板。

小例子:

library(ggplot2)
ggplot(mpg, aes(displ, hwy)) +
    geom_point() +
    facet_wrap(~ cyl + drv)

每个面板顶部的标签有两行,我想减少两行标签文本之间的间距。我应该如何正确地做到这一点?

我试过了:

ggplot(mpg, aes(displ, hwy)) +
    geom_point() +
    facet_wrap(~ cyl + drv) +
    theme(
        strip.text = element_text(
            margin = margin(t = 0, r = 0, b = 0, l = 0, unit = "pt")
        )
    )

但这不起作用。

提前致谢。

【问题讨论】:

    标签: r ggplot2


    【解决方案1】:

    您可以指定一个贴标机,将标签放入同一个条带,而不是创建两个条带:

    ggplot(mpg, aes(displ, hwy)) +
      geom_point() +
      facet_wrap(~ cyl + drv, 
                 labeller = function (labels) {
                   labels <- lapply(labels, as.character)
                   list(do.call(paste, c(labels, list(sep = "\n"))))
                 }) 
    

    【讨论】:

      【解决方案2】:

      公认的答案是实现所需输出的最直接和最简单的方法,但我利用这个问题作为了解更多关于使用 grobs 的机会,我想我会分享我学到的东西。

      要修改构面标签之间的间距,我们可以操纵底层的 grobs。为此,首先生成绘图 grob:

      library(ggplot2)
      library(grid)
      p <- ggplot(mpg, aes(displ, hwy)) +
          geom_point() +
          facet_wrap(~ cyl + drv)
      g <- ggplotGrob(p)
      

      现在,我们可以检查 grobs。 facet strips 是 grobs 47 到 55(9 个 grobs),我们注意到每个条带 grob 实际上是一个 grobs 表:

      g
      # TableGrob (21 x 15) "layout": 62 grobs
      #     z         cells        name                                   grob
      # 1   0 ( 1-21, 1-15)  background        rect[plot.background..rect.614]
      # 2   1 ( 7- 7, 4- 4)   panel-1-1                gTree[panel-1.gTree.33]
      # 3   1 (12-12, 4- 4)   panel-2-1                gTree[panel-4.gTree.78]
      # ...
      # 47  2 (16-16, 4- 4) strip-t-1-3                          gtable[strip]
      # 48  2 (16-16, 8- 8) strip-t-2-3                          gtable[strip]
      # 49  2 (16-16,12-12) strip-t-3-3                          gtable[strip]
      # 50  2 (11-11, 4- 4) strip-t-1-2                          gtable[strip]
      # 51  2 (11-11, 8- 8) strip-t-2-2                          gtable[strip]
      # 52  2 (11-11,12-12) strip-t-3-2                          gtable[strip]
      # 53  2 ( 6- 6, 4- 4) strip-t-1-1                          gtable[strip]
      # 54  2 ( 6- 6, 8- 8) strip-t-2-1                          gtable[strip]
      # 55  2 ( 6- 6,12-12) strip-t-3-1                          gtable[strip]
      # 56  4 ( 4- 4, 4-12)      xlab-t                         zeroGrob[NULL]
      # ...
      

      专注于 grob 47,我们可以深入了解结构...

      str(g$grobs[[47]], m = 1)
      str(g$grobs[[47]]$grobs, m = 1)
      str(g$grobs[[47]]$grobs[[1]], m = 1)
      str(g$grobs[[47]]$grobs[[1]]$children, m = 1)
      str(g$grobs[[47]]$grobs[[1]]$children[[2]], m = 1)
      str(g$grobs[[47]]$grobs[[1]]$children[[2]]$children, m = 1)
      

      ...直到我们找出如何指定构面标签:

      str(g$grobs[[47]]$grobs[[1]]$children[[2]]$children[[1]], m = 1)
      # List of 11
      #  $ label        : chr "8"
      #  $ x            :Class 'unit'  atomic [1:1] 0.5
      #   .. ..- attr(*, "valid.unit")= int 0
      #   .. ..- attr(*, "unit")= chr "npc"
      #  $ y            :Class 'unit'  atomic [1:1] 0.5
      #   .. ..- attr(*, "valid.unit")= int 0
      #   .. ..- attr(*, "unit")= chr "npc"
      #  $ just         : chr "centre"
      #  $ hjust        : NULL
      #  $ vjust        : NULL
      #  $ rot          : num 0
      #  $ check.overlap: logi FALSE
      #  $ name         : chr "GRID.text.322"
      #  $ gp           :List of 6
      #   ..- attr(*, "class")= chr "gpar"
      #  $ vp           : NULL
      #  - attr(*, "class")= chr [1:3] "text" "grob" "gDesc"
      

      现在,我们只需更改 y 的值,使顶部 grob 的标签靠近底部,底部 grob 的标签靠近顶部。我只对最左侧列中的刻面条执行此操作,以便我们可以看到差异:

      for (i in c(47, 50, 53)) {
        g$grobs[[i]]$grobs[[1]]$children[[2]]$children[[1]]$y = unit(0.1, "npc")
        g$grobs[[i]]$grobs[[2]]$children[[2]]$children[[1]]$y = unit(0.9, "npc")
      }
      grid.newpage()
      grid.draw(g)
      

      输出:

      【讨论】: