【问题标题】:Decreasing space between legend columns in ggplot2减少ggplot2中图例列之间的空间
【发布时间】:2017-03-17 14:14:15
【问题描述】:

这里是一些示例代码,它提供了一个 2 列的图例。我想减少图例两列之间的空间(见下文)。

library(ggplot2)

labels <- c(expression(""^13*CH[4]),
            expression(""^13*CH[4]~"+"~SO[4]^{2-''}),
            expression(""^13*CH[4]~"+"~MoO[4]^{2-''})) 

ggplot(aes(mpg, wt, colour = factor(cyl), shape=factor(cyl)), 
       data = mtcars) +
      geom_point() +
      scale_colour_manual(values=c("red", "green", "blue"), label=labels)+
      scale_shape_manual(values = c(4,5,6), label=labels)+
      theme(legend.position = "bottom",
            legend.text.align = 0,
            legend.text = element_text(size=8),
            legend.key.size = unit(0.8, 'lines')) + 
      guides(col = guide_legend("", ncol=2), shape=guide_legend("", col=2))

这是我现实生活中的问题:

图的右侧需要额外的空间,因为那里的三个因子水平包含更多的字符。但是,我真的受到情节大小的限制。因此,我想减少图例两行之间的空间。 我还想保持左侧最底部的因子水平不变,而不添加额外的行。

【问题讨论】:

  • 请提供一个可重现的示例,以便我们可以解决您的问题。您可以提供一个带有简单绘图的虚拟数据框,该绘图创建对您来说有问题的图例,因此其他人可以帮助提供解决方案,而不必担心重现问题。请参阅stackoverflow.com/q/5963269/446149 了解如何提供一个良好的可重现示例
  • 已经有带有虚拟数据集的可重现玩具代码。它编码具有两列的图例。我不认为发布所有标签表达式会有所帮助,而是会夸大问题。
  • 我添加了一些表达来澄清。

标签: r ggplot2


【解决方案1】:

根据您的示例,我对其进行了一些简化:

创建有问题的情节:

library(ggplot2)

labels <- c("short1", "loooooooooooooooooong", "short2")

plt <- ggplot(aes(mpg, wt, colour = factor(cyl), shape=factor(cyl)), 
       data = mtcars) +
  geom_point() +
  scale_colour_manual(values=c("red", "green", "blue"), label=labels)+
  scale_shape_manual(values = c(4,5,6), label=labels)+
  theme(legend.position = "bottom",
        legend.text.align = 0,
        legend.text = element_text(size=8),
        legend.key.size = unit(0.8, 'lines')) + 
  guides(col = guide_legend("", ncol=2), shape=guide_legend("", col=2))
plot(plt)

提取图例并对其进行调整

我使用this answer从情节中提取图例:

#Extract Legend 
g_legend<-function(a.gplot){ 
  tmp <- ggplot_gtable(ggplot_build(a.gplot)) 
  leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box") 
  legend <- tmp$grobs[[leg]] 
  return(legend)} 

legend <- g_legend(plt) 

然后打印出来:

grid.newpage()
grid.draw(legend) 

然后我探索了图例中的 grobs,发现了宽度字段:

legend$grobs[[1]]$widths
 [1] 0.2cm              0cm                0.1524cm           0.4064cm           0.0762cm           3.22791666666667cm 0.0762cm           0.4064cm           0.0762cm          
[10] 0.79375cm          0.2cm             
> 

显然这 3.227 厘米太大了,所以我只是改变了它们:

legend$grobs[[1]]$widths[6] <- unit(1.5, "cm")

并绘制它:

grid.newpage()
grid.draw(legend)

将修复应用于全局图:

最后的步骤是在 ggplot 上复制它:

对全局绘图应用相同的手动校正:

# this is how the legend was extracted:
plt_gtable <- ggplot_gtable(ggplot_build(plt)) 
leg <- which(sapply(plt_gtable$grobs, function(x) x$name) == "guide-box") 

# Replace the legend with our modified legend:
plt_gtable$grobs[[leg]] <- legend

然后重新绘制:

grid.newpage()
grid.draw(plt_gtable)

【讨论】:

  • 作为一个小旁注,需要替换内部情节“Id”,例如名字(传奇$grobs)
  • 我将其替换为通用的$grobs[[1]]。如果情节有多个图例,您可以使用$grobs[[2]]