有没有办法改变ggplot2中图例项之间的间距?

Posted

技术标签:

【中文标题】有没有办法改变ggplot2中图例项之间的间距?【英文标题】:Is there a way to change the spacing between legend items in ggplot2? 【发布时间】:2012-07-07 04:38:44 【问题描述】:

有没有办法改变 ggplot2 中图例项之间的间距?我目前有

legend.position ="top" 

自动生成水平图例。但是,项目的间距非常接近,我想知道如何将它们分开更远。

【问题讨论】:

现在opts 已被贬值,因此有一个当前的解决方案会很有用。 这里:pastebin.com/NnxMiTeH Tung 的回答,目前在这个帖子的底部,有 2018 年 7 月的更新。错误已得到修复,不再需要像上面的 pastebin 中那样的 hacky 解决方法。 【参考方案1】:

2018 年 7 月发布的ggplot2 v3.0.0 具有修改legend.spacing.xlegend.spacing.ylegend.text 的工作选项。

示例:增加图例键之间的水平间距

library(ggplot2)

ggplot(mtcars, aes(factor(cyl), fill = factor(cyl))) + 
  geom_bar() +
  coord_flip() +
  scale_fill_brewer("Cyl", palette = "Dark2") +
  theme_minimal(base_size = 14) +
  theme(legend.position = 'top', 
        legend.spacing.x = unit(1.0, 'cm'))

注意:如果只想扩大图例文本右侧的间距,请使用stringr::str_pad()

示例:将图例键标签移动到底部并增加垂直间距

ggplot(mtcars, aes(factor(cyl), fill = factor(cyl))) + 
  geom_bar() +
  coord_flip() +
  scale_fill_brewer("Cyl", palette = "Dark2") +
  theme_minimal(base_size = 14) +
  theme(legend.position = 'top', 
        legend.spacing.x = unit(1.0, 'cm'),
        legend.text = element_text(margin = margin(t = 10))) +
  guides(fill = guide_legend(title = "Cyl",
                             label.position = "bottom",
                             title.position = "left", title.vjust = 1)) 

例如:scale_fill_xxx & guide_colorbar

ggplot(mtcars, aes(mpg, wt)) +
  geom_point(aes(fill = hp), pch = I(21), size = 5)+
  scale_fill_viridis_c(guide = FALSE) +
  theme_classic(base_size = 14) +
  theme(legend.position = 'top', 
        legend.spacing.x = unit(0.5, 'cm'),
        legend.text = element_text(margin = margin(t = 10))) +
  guides(fill = guide_colorbar(title = "HP",
                               label.position = "bottom",
                               title.position = "left", title.vjust = 1,
                               # draw border around the legend
                               frame.colour = "black",
                               barwidth = 15,
                               barheight = 1.5)) 


对于垂直图例,设置legend.key.size 只会增加图例键的大小,而不是它们之间的垂直空间

ggplot(mtcars) +
  aes(x = cyl, fill = factor(cyl)) +
  geom_bar() +
  scale_fill_brewer("Cyl", palette = "Dark2") +
  theme_minimal(base_size = 14) +
  theme(legend.key.size = unit(1, "cm"))

为了增加图例键之间的距离,需要修改legend-draw.r函数。请参阅此issue 了解更多信息

# function to increase vertical spacing between legend keys
# @clauswilke
draw_key_polygon3 <- function(data, params, size) 
  lwd <- min(data$size, min(size) / 4)
  
  grid::rectGrob(
    width = grid::unit(0.6, "npc"),
    height = grid::unit(0.6, "npc"),
    gp = grid::gpar(
      col = data$colour,
      fill = alpha(data$fill, data$alpha),
      lty = data$linetype,
      lwd = lwd * .pt,
      linejoin = "mitre"
    ))


### this step is not needed anymore per tjebo's comment below
### see also: https://ggplot2.tidyverse.org/reference/draw_key.html
# register new key drawing function, 
# the effect is global & persistent throughout the R session
# GeomBar$draw_key = draw_key_polygon3

ggplot(mtcars) +
  aes(x = cyl, fill = factor(cyl)) +
  geom_bar(key_glyph = "polygon3") +
  scale_fill_brewer("Cyl", palette = "Dark2") +
  theme_minimal(base_size = 14) +
  theme(legend.key = element_rect(color = NA, fill = NA),
        legend.key.size = unit(1.5, "cm")) +
  theme(legend.title.align = 0.5)

【讨论】:

感谢您指出这一点。这是一个很棒的新功能,我一直在使用@user2568648 的dirty-fix,哈哈! 您增加图例键之间垂直间距的功能是我发现的唯一解决方案,它完全符合我的要求并且易于使用。谢谢! 我一直回到这个线程 :D 在当前的 ggplot2 中,可以(也许应该?)而不是永久覆盖 GeomBar 对象,而是使用 key_glyph 参数:geom_bar(..., key_glyph = "polygon3") @tjebo:这很简洁。我已经更新了我的答案。谢谢你告诉我! @Anke 您仍然需要根据 Tungs 的回答定义函数【参考方案2】:

我认为最好的选择是在guides 中使用guide_legend

p + guides(fill=guide_legend(
                 keywidth=0.1,
                 keyheight=0.1,
                 default.unit="inch")
      )

注意default.unit的使用,无需加载grid包。

【讨论】:

这需要更多的支持,其他答案已经过时了。 这可能适用于水平图例。但是,对于绘图右侧的垂直图例,这只会增加键的高度,而不是键之间的间距。我的图例键仍然非常接近。 正如 Mushin 所说,这没有抓住重点,就像其他答案一样,如果图例是 VERTICAL 它会拉伸图例键(例如线段)而不填充它们之间的空间键。 与 geom_line 和 geom_point 配合得很好。【参考方案3】:

我用来在水平图例中添加空格的简单修复,只需在标签中添加空格(请参阅下面的摘录):

  scale_fill_manual(values=c("red","blue","white"),
                    labels=c("Label of category 1          ",
                             "Label of category 2          ",
                             "Label of category 3"))

【讨论】:

这是迄今为止处理该问题的唯一答案!如果有很多条目,这可能会有所帮助:scale_fill_manual(values=values, labels=setNames(paste(labels, " "), entries)) 技术上不是很好,尤其是当您必须将这些空间引入因子级别时,但这是唯一可行的解​​决方案。 或者我们可以使用str_pad 让生活更轻松一些【参考方案4】:

要在图例中的条目之间添加间距,请调整主题元素 legend.text 的边距。

在每个图例标签的右侧添加 30pt 的空间(可能对水平图例有用):

p + theme(legend.text = element_text(
    margin = margin(r = 30, unit = "pt")))

在每个图例标签左侧添加 30pt 的空间(可能对垂直图例有用):

p + theme(legend.text = element_text(
    margin = margin(l = 30, unit = "pt")))

对于ggplot2 对象p。关键字是legend.textmargin

[关于编辑的注意事项:当这个答案首次发布时,有一个错误。该错误现已修复]

【讨论】:

该错误现已修复,这应该是公认的答案。 另请参阅 Tung 对 2018 年 7 月有关这些问题的更新的回答。 是的,这就是答案 如果您想在每个条目底部和顶部的垂直图例中的项目之间添加空格,请尝试类似margin = margin(t = 5, b = 5, unit = "pt")【参考方案5】:

现在optsggplot2 包中已弃用,应使用函数theme

library(grid) # for unit()
... + theme(legend.key.height=unit(3,"line"))
... + theme(legend.key.width=unit(3,"line"))

【讨论】:

这个解决方案改变了盒子的高度/宽度,而不是它们之间的间距。【参考方案6】:

看起来最好的方法(2018 年)是在 theme 对象下使用 legend.key.size。 (例如,参见here)。

#Set-up:
    library(ggplot2)
    library(gridExtra)

    gp <- ggplot(data = mtcars, aes(mpg, cyl, colour = factor(cyl))) +
        geom_point()

如果您使用theme_bw(),这真的很容易:

  gpbw <- gp + theme_bw()

#Change spacing size:

  g1bw <- gpbw + theme(legend.key.size = unit(0, 'lines'))
  g2bw <- gpbw + theme(legend.key.size = unit(1.5, 'lines'))
  g3bw <- gpbw + theme(legend.key.size = unit(3, 'lines'))

  grid.arrange(g1bw,g2bw,g3bw,nrow=3)

但是,否则效果不佳(例如,如果您的图例符号需要灰色背景):

  g1 <- gp + theme(legend.key.size = unit(0, 'lines'))
  g2 <- gp + theme(legend.key.size = unit(1.5, 'lines'))
  g3 <- gp + theme(legend.key.size = unit(3, 'lines'))

  grid.arrange(g1,g2,g3,nrow=3)

#Notice that the legend symbol squares get bigger (that's what legend.key.size does). 

#Let's [indirectly] "control" that, too:
  gp2 <- g3
  g4 <- gp2 + theme(legend.key = element_rect(size = 1))
  g5 <- gp2 + theme(legend.key = element_rect(size = 3))
  g6 <- gp2 + theme(legend.key = element_rect(size = 10))

  grid.arrange(g4,g5,g6,nrow=3)   #see picture below, left

请注意,白色方块开始阻挡图例标题(如果我们不断增加值,最终会阻挡图形本身)。

  #This shows you why:
    gt <- gp2 + theme(legend.key = element_rect(size = 10,color = 'yellow' ))

我还没有找到解决上述问题的解决方法... 如果你有想法,请在 cmets 中告诉我,我会相应地更新!

我想知道是否有某种方法可以使用 $layers 重新分层事物...

【讨论】:

使legend.key 透明:theme(legend.key = element_rect(size = 30,color=alpha("transparent",0))) 这是最直接的答案,也是最容易使用的 imo【参考方案7】:

来自 Koshke 在 ggplot2 上的工作和他的博客 (Koshke's blog)

... + theme(legend.key.height=unit(3,"line")) # Change 3 to X
... + theme(legend.key.width=unit(3,"line")) # Change 3 to X

在控制台中输入 theme_get() 以查看其他可编辑的图例属性。

【讨论】:

感谢您的建议和 Koshke 博客的链接!然而不幸的是,这似乎改变了盒子的大小,而不是项目之间的间距。 您可以使用某种类型的覆盖 grob 来“伪造”它。但我认为没有办法在图例中获得额外的间距。这是我在 ggplot2 的邮件列表中唯一提到的:groups.google.com/forum/?fromgroups#!topic/ggplot2/PhkJpP8zJuM 我可以使用它成功地增加图例之间的间距。使用负数有助于减少图例之间的间距。【参考方案8】:

使用其中任何一个

legend.spacing = unit(1,"cm")
legend.spacing.x = unit(1,"cm")
legend.spacing.y = unit(1,"cm")

【讨论】:

我的问题是图例的标签最终占据了额外空白区域的中间部分,而不是在图例的彩色框之间生成空间。我发现这里提供的关于在theme(legend.text) 下填充的答案是最令人满意的。

以上是关于有没有办法改变ggplot2中图例项之间的间距?的主要内容,如果未能解决你的问题,请参考以下文章

R语言ggplot2可视化自定义图例标签间距实战:自定义图例标签间距自定义图例与图像之间的间距

R语言ggplot2可视化自定义多个图例(legend)标签之间的距离实战(例如,改变数据点颜色和数据点大小图例之间的距离)

如何将图例添加到 ggplot2 中的多行?

echarts 图例之间的间距怎么设置

增加图例字体大小ggplot2

R语言可视化包ggplot2改变图例(legend)标签实战