【问题标题】:Separate y-axis labels by facet OR remove legend but keep the space按构面分隔 y 轴标签或删除图例但保留空间
【发布时间】:2014-07-07 22:37:50
【问题描述】:

好的,我对自制的 ggplot 感到困惑。

我想做的是有一个三行一列的多面图,每个面都有不同的 y 轴 标签。 y轴的单位都是一样的。这将是最方便的,但谷歌搜索告诉我这可能是不可能的。

另外,我找到了使用 grid.arrange 的this 解决方案,这似乎可行。但是,我只想为一个情节保留一个图例,并将其从其他两个情节中删除,但保持间距就好像它仍然存在一样,以便一切都很好。几年前有人有same problem,但建议的解决方案已被贬值,我无法弄清楚如何使其在现代ggplot中工作。

任何帮助表示赞赏!使用构面将是最简单的!

在使用下面的 user20560 的 gridArrange 解决方案后,添加了绘图副本。快到了,只是想拿回顶部和底部刻面面板周围的盒子!

【问题讨论】:

    标签: r ggplot2


    【解决方案1】:

    我假设(可能是错误的)您想要添加单独的 y 轴标题而不是轴标签。 [如果是你想要不同的标签,你可以使用facet_grid中的scales参数]

    会有一种 ggplot 方法来做到这一点,但这里有几种方法可以让您自己调整 grobs。

    所以以 mtcars 数据集为例

    library(ggplot2)
    library(grid)
    library(gridExtra)
    

    一种方式

    p <- ggplot(mtcars, aes(mpg, wt, col=factor(vs))) +   geom_point() + 
                                     facet_grid(gear ~ .)
    
    # change the y axis labels manually
    g <- ggplotGrob(p)
    yax <- which(g$layout$name=="ylab")
    
    # define y-axis labels
    g[["grobs"]][[yax]]$label <- c("aa","bb", "cc")
    
    # position of labels (ive just manually specified)
    g[["grobs"]][[yax]]$y <- grid::unit(seq(0.15, 0.85, length=3),"npc")
    
    grid::grid.draw(g)
    



    或者使用grid.arrange

    # Create a plot for each level of grouping variable and y-axis label
    p1 <- ggplot(mtcars[mtcars$gear==3, ], aes(mpg, wt, col=factor(vs))) + 
                                     geom_point() + labs(y="aa") + theme_bw()
    p2 <- ggplot(mtcars[mtcars$gear==4, ], aes(mpg, wt, col=factor(vs))) +  
                                     geom_point() + labs(y="bb") + theme_bw()
    p3 <- ggplot(mtcars[mtcars$gear==5, ], aes(mpg, wt, col=factor(vs))) +  
                                     geom_point() + labs(y="cc") + theme_bw()
    
    # remove legends from two of the plots
    g1 <- ggplotGrob(p1)
    g1[["grobs"]][[which(g1$layout$name=="guide-box")]][["grobs"]] <- NULL
    
    g3 <- ggplotGrob(p3)
    g3[["grobs"]][[which(g3$layout$name=="guide-box")]][["grobs"]] <- NULL
    
    gridExtra::grid.arrange(g1,p2,g3)
    

    如果您要添加的是轴标题,我应该问为什么您想要不同的标题 - 刻面条文本可以不做吗?

    【讨论】:

    • 这确实是我所追求的轴标题。我没有想到只使用分面条文本的(明显的)答案,但我认为通过轴标签使用标题更清晰、更标准,因为它们实际上是在描述单位(所有三个图的单位都是毫米,但它们是不同的东西)。您使用网格排列的上述解决方案效果很好,除了它还删除了每个方面面板周围的框。我不是很精通grob,所以我不知道该怎么做。我会尝试在此处的某个地方添加该情节的副本....
    • @IcebergSlim;您可以更改panel.border 的厚度。例如,使用上面的图 p3:p3 + theme_bw() + theme(panel.border=element_rect(fill=NA, colour = "black", size=2)),尽管可能只是 theme_bw() 就足够了。您可能还会发现更改主题 plot.margin 以控制排列图之间的空间很有用。
    • 嗯....面板边框对我没有多大作用。在我进入那里并操纵 grob 之前,边框会正确显示。我不确定为什么更改引导框会影响绘图边界。也许我正在进入这里的错误领域。感谢您的建议!
    • @IcebergSlim;抱歉,答案代码中的错误 - 我错过了 [["grobs"]] - 已更正 - 现在看起来还可以
    • @user3420448 ;由于 ggplot2 的几次重大重写改变了内部绘图对象结构,这似乎不再起作用。事实证明,这类答案非常不稳定。其他一些答案可能有助于/提供替代方法。
    【解决方案2】:

    按照 Axeman 和 aosmith 的 cmets(谢谢),这是一种使用 ggplot2 版本 2.2.0 的构面标签的方法

    library(ggplot2) # From sessionInfo(): ggplot2_2.2.0
    
    ggplot(mtcars, aes(mpg, wt, col=factor(vs))) + geom_point() + 
      facet_grid(gear ~ ., switch = 'y') +
      theme( axis.title.y = element_blank(), # remove the default y-axis title, "wt"
             strip.background = element_rect(fill = 'transparent'), # replace the strip backgrounds with transparent
             strip.placement = 'outside', # put the facet strips on the outside
             strip.text.y = element_text(angle=180)) # rotate the y-axis text (optional)
    # (see ?ggplot2::theme for a list of theme elements (args to theme()))
    

    【讨论】:

    • 听起来你想要switch.placement = "outside" 用于ggplot2_2.2.0。例如,请参阅答案here
    【解决方案3】:

    我知道这是一个旧帖子,但在找到它后,我无法得到@user20560 的工作回复。

    我已将@user20560 的grid.extra 方法编辑如下:

    library(ggplot2)
    library(gridExtra)
    library(grid)
    
    # Create a plot for each level of grouping variable and y-axis label
    p1 <- ggplot(mtcars[mtcars$gear==3, ], aes(mpg, wt, col=factor(vs))) + 
      geom_point() + labs(y="aa") + theme_bw()
    p2 <- ggplot(mtcars[mtcars$gear==4, ], aes(mpg, wt, col=factor(vs))) +  
      geom_point() + labs(y="bb") + theme_bw()
    p3 <- ggplot(mtcars[mtcars$gear==5, ], aes(mpg, wt, col=factor(vs))) +  
      geom_point() + labs(y="cc") + theme_bw()
    
    # get the legend as a grob
    legend <- ggplotGrob(p1)
    legend <- legend$grobs[[which(legend$layout$name=="guide-box")]]
    lheight <- sum(legend$height)
    lwidth <- sum(legend$width)
    
    # remove the legend from all the plots
    p1 <- p1 + theme(legend.position = 'none')
    p2 <- p2 + theme(legend.position = 'none')
    p3 <- p3 + theme(legend.position = 'none')
    
    # force the layout to the right side
    layoutMat <- matrix(c(1,2,3,4,4,4),ncol = 2)
    
    grid.arrange(p1,p2,p3,legend, layout_matrix = layoutMat, ncol = 2, 
                 widths = grid::unit.c(unit(1,'npc') - lwidth, lwidth))
    

    这个例子有点特定于这个特定的布局。在ggplot2wiki上有一个更通用的方法。

    【讨论】:

    • 这些有不同的 x 轴。我相信 OP 想要三个共享 x 轴但具有不同 y 轴的图。
    • 根据 OP 的最后编辑,图片显示了不同的 x 轴。如果您想共享 x 轴,则可以使用 facet_grid,如下面@Richard DiSalvo 的回复所示。
    【解决方案4】:

    我也很难让the answer of user20560(上图)中的第一种方法起作用。这可能是因为 ggplot2 的内部结构已经进化,并且不能保证这些内部结构应该保持不变。无论如何,这是一个当前有效的版本:

    library(ggplot2) # From sessionInfo(): ggplot2_2.1.0
    library(grid)
    
    p <- ggplot(mtcars, aes(mpg, wt, col=factor(vs))) + geom_point() + facet_grid(gear ~ .)
    g <- ggplotGrob(p)
    yax <- which(g$layout$name == "ylab")
    g[["grobs"]][[yax]]$children[[1]]$label <- c('fo','bar','foobar')
    g[["grobs"]][[yax]]$children[[1]]$y <- grid::unit(seq(0.15, 0.85, length=3), "npc")
    grid.draw(g)
    

    请注意,这是保留刻面且不重复 x 轴的方法。

    【讨论】:

    • 使用当前ggplot2 版本的一个好方法是在facet_grid 中使用switch = 'y',然后使用主题设置删除y 轴标签并去除背景。不需要grid 操作。
    猜你喜欢
    • 1970-01-01
    • 2018-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-22
    • 2023-02-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多