【问题标题】:ggplot2: Using gtable to move strip labels to top of panel for facet_gridggplot2:使用 gtable 将条形标签移动到 facet_grid 面板的顶部
【发布时间】:2015-05-14 13:04:51
【问题描述】:

我正在使用facet_grid 创建一个图形,以在 y 轴上刻画一个分类变量。我决定不使用facet_wrap,因为我需要space = 'free'labeller = label_parsed。我的标签很长,右侧有一个图例,因此我想将标签从面板右侧移动到面板顶部。

这里有一个例子来说明我在哪里卡住了。

library(ggplot2)
library(gtable)

mt <- ggplot(mpg, aes(x = cty, y = model)) + geom_point() +
  facet_grid(manufacturer ~ ., scales = 'free', space = 'free') +
  theme_minimal() +
  theme(panel.margin = unit(0.5, 'lines'), strip.text.y = element_text(angle = 0))

现在我想将带状文本从每个面板的右侧移动到每个面板的顶部。我可以存储条形标签的 grobs 并将它们从图中删除:

grob <- ggplotGrob(mt)
strips.y <- gtable_filter(grob, 'strip-right')
grob2 <- grob[,-5]

但现在我被 rbind 卡住了 - 将 grobs 退回,所以标签会出现在面板的顶部。

另一种可能的解决方案是使用facet_wrap,然后重新调整面板as discussed in another question 的大小,但在这种情况下,我必须手动更改构面上的标签,因为facet_wrap 没有labeller = label_parsed .

我会很感激任何一种方法的建议!

感谢阅读,

汤姆

【问题讨论】:

    标签: r ggplot2 facet gtable


    【解决方案1】:

    这是您的第一种方法。它在每个面板上方插入一行,抓住条形 grobs(在右侧),并将它们插入新行。

    library(ggplot2)
    library(gtable)
    library(grid)
    
    mt <- ggplot(mpg, aes(x = cty, y = model)) + geom_point() +
      facet_grid(manufacturer ~ ., scales = 'free', space = 'free') +
      theme(panel.spacing = unit(0.5, 'lines'), 
             strip.text.y = element_text(angle = 0))
    
    # Get the gtable
    gt <- ggplotGrob(mt)
    
    # Get the position of the panels in the layout
    panels <-c(subset(gt$layout, grepl("panel", gt$layout$name), se=t:r))
    
    # Add a row above each panel
    for(i in rev(panels$t-1)) gt = gtable_add_rows(gt, unit(.5, "lines"), i)
    
    # Get the positions of the panels and the strips in the revised layout
    panels <-c(subset(gt$layout, grepl("panel", gt$layout$name), se=t:r))
    strips <- c(subset(gt$layout, grepl("strip-r", gt$layout$name), se=t:r))
    
    # Get the strip grobs
    stripText = gtable_filter(gt, "strip-r")
    
    # Insert the strip grobs into the new rows
    for(i in 1:length(strips$t)) gt = gtable_add_grob(gt, stripText$grobs[[i]]$grobs[[1]],  t=panels$t[i]-1, l=4)
    
    # Remove the old strips
    gt = gt[,-5]
    
    # For this plot - adjust the heights of the strips and the empty row above the strips
    for(i in panels$t) {
       gt$heights[i-1] = unit(0.8, "lines")
       gt$heights[i-2] = unit(0.2, "lines")
       }
    
    # Draw it
    grid.newpage()
    grid.draw(gt)
    

    或者,您可以使用facet_wrap_labeller 函数available from here 实现第二种方法。

    library(ggplot2)
    library(gtable)
    
    mt <- ggplot(mpg, aes(x = cty, y = model)) + geom_point() +
       facet_wrap(~ manufacturer, scales = "free_y", ncol = 1) +
       theme(panel.margin = unit(0.2, 'lines'))
    
    
    facet_wrap_labeller <- function(gg.plot, labels=NULL) {
      require(gridExtra)
    
      g <- ggplotGrob(gg.plot)
      gg <- g$grobs      
      strips <- grep("strip_t", names(gg))
    
      for(ii in seq_along(labels))  {
        modgrob <- getGrob(gg[[strips[ii]]], "strip.text", 
                           grep=TRUE, global=TRUE)
        gg[[strips[ii]]]$children[[modgrob$name]] <- editGrob(modgrob,label=labels[ii])
      }
    
      g$grobs <- gg
      class(g) = c("arrange", "ggplot",class(g)) 
      return(g)
    }
    
    ## Number of y breaks in each panel
    g <- ggplot_build(mt) 
    N <- sapply(lapply(g$panel$ranges, "[[", "y.major"), length)
    
    # Some arbitrary strip texts
    StripTexts = expression(gamma[1], sqrt(gamma[2]), C, `A really incredibly very very very long label`, gamma[5], alpha[1], alpha[2], `Land Rover`, alpha[1], beta[2], gamma^2, delta^2, epsilon[2], zeta[3], eta[4] )
    
     # Apply the facet_wrap_labeller function
    gt = facet_wrap_labeller(mt, StripTexts)
    
    # Get the position of the panels in the layout
    panels <- gt$layout$t[grepl("panel", gt$layout$name)]
    
    # Replace the default panel heights with relative heights
    gt$heights[panels] <- lapply(N, unit, "null")
    
    # Draw it
    gt
    

    【讨论】:

    • 这太棒了,谢谢。我刚刚对您的第一种方法进行了一些小改动,以便我可以将其变成一个函数:for(i in 1:length(strips$t)) gt = gtable_add_grob(gt, stripText$grobs[[i]], t=panels$t[i]-1, l=4, r=4) -> for(i in 1:length(strips$t)) gt = gtable_add_grob(gt, stripText$grobs[[i]], t = panels$t[i]-1, l = min(panels$l), r = max(panels$r)) 插入新的条带,gt = gt[,-5] -> gt &lt;- gt[,-c(min(strips$l), max(strips$r))] 删除旧条带.
    • 更新这个适用于当前 ggplot2?条带的标签不同等等。我无法完成这项工作。
    • @JanStanstrup 第一个版本已编辑并按预期工作 - 目前。请耐心等待 - 第二个版本即将推出。
    【解决方案2】:

    我正在努力解决类似的问题,但将标签放在底部。我使用了这个答案的代码改编。而最近发现

    ggplot2 ver.2.2.1.0 (http://docs.ggplot2.org/current/facet_grid.html)

    ~facet_grid(.~variable,switch='x')

    对我来说效果很好的选项。

    【讨论】:

      猜你喜欢
      • 2022-01-18
      • 1970-01-01
      • 1970-01-01
      • 2020-09-09
      • 1970-01-01
      • 2018-11-03
      • 2012-03-11
      • 2022-01-23
      • 1970-01-01
      相关资源
      最近更新 更多