如何使 ggplot2 中的图例与我的情节高度相同?

Posted

技术标签:

【中文标题】如何使 ggplot2 中的图例与我的情节高度相同?【英文标题】:How can I make the legend in ggplot2 the same height as my plot? 【发布时间】:2013-10-13 10:34:29 【问题描述】:

我使用ggplot2(版本 0.9.3.1)在 R(版本 R 版本 3.0.1 (2013-05-16))中生成了一个简单的图,它显示了一组数据的相关系数。目前,绘图右侧的图例颜色条是整个绘图大小的一小部分。

我希望图例颜色条与图的高度相同。我以为我可以使用legend.key.height 来做到这一点,但我发现事实并非如此。我调查了gridunit 函数,发现里面有一些标准化的单位,但是当我尝试它们时(unit(1, "npc")),颜色条太高了,离开了页面。

如何使图例与图本身的高度相同?

下面是一个完整的独立示例:

# Load the needed libraries
library(ggplot2)
library(grid)
library(scales)
library(reshape2)

# Generate a collection of sample data
variables = c("Var1", "Var2", "Var3")
data = matrix(runif(9, -1, 1), 3, 3)
diag(data) = 1
colnames(data) = variables
rownames(data) = variables

# Generate the plot
corrs = data
ggplot(melt(corrs), aes(x = Var1, y = Var2, fill = value)) +
  geom_tile() +
  geom_text(parse = TRUE, aes(label = sprintf("%.2f", value)), size = 3, color = "white") +
  theme_bw() +
  theme(panel.border = element_blank(),
        axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1),
        aspect.ratio = 1,
        legend.position = "right",
        legend.key.height = unit(1, "inch")) +
        labs(x = "", y = "", fill = "", title = "Correlation Coefficients") +
        scale_fill_gradient2(limits = c(-1, 1), expand = c(0, 0),
                             low = muted("red"),
                             mid = "black",
                             high = muted("blue"))

【问题讨论】:

请发布一个最小的独立的可重现示例 好的,问题已编辑为具有完整的可运行示例 【参考方案1】:

编辑更新到 ggplot v3.0.0

这很乱,但是基于this answer,并且深入研究ggplot grob,可以精确定位图例。

# Load the needed libraries
library(ggplot2)
library(gtable)  # 
library(grid)
library(scales)
library(reshape2)

# Generate a collection of sample data
variables = c("Var1", "Var2", "Var3")
data = matrix(runif(9, -1, 1), 3, 3)
diag(data) = 1
colnames(data) = variables
rownames(data) = variables

# Generate the plot
corrs = data
plot  = ggplot(melt(corrs), aes(x = Var1, y = Var2, fill = value)) + 
   geom_tile() +
   theme_bw() + 
   theme(panel.border = element_blank()) +
   theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1)) +
   theme(aspect.ratio = 1) +
   # theme(legend.position = "right", legend.key.height = unit(1, "inch")) +
   labs(x = "", y = "", fill = "", title = "Correlation Coefficients") +
   scale_fill_gradient2(limits = c(-1, 1), breaks = c(-1, -.5, 0, .5, 1), expand = c(0,0), 
      low = muted("red"), mid = "black", high = muted("blue")) +  # Modified line
   geom_text(parse = TRUE, aes(label = sprintf("%.2f", value)), size = 3, color = "white") +
   scale_x_discrete(expand = c(0,0)) +  # New line
   scale_y_discrete(expand = c(0,0))    # New line
plot

# Get the ggplot grob
gt = ggplotGrob(plot)

# Get the legend
leg = gtable_filter(gt, "guide-box")

# Raster height
leg[[1]][[1]][[1]][[1]][[1]][[2]]$height = unit(1, "npc")

# Positions for labels and tick marks - five breaks, therefore, five positions
pos = unit.c(unit(0.01,"npc"), unit(.25, "npc"), unit(.5, "npc"), unit(.75, "npc"), unit(.99, "npc"))

# Positions the labels 
leg[[1]][[1]][[1]][[1]][[1]][[3]]$children[[1]]$y = pos

# Positions the tick marks
leg[[1]][[1]][[1]][[1]][[1]][[5]]$y0 = pos
leg[[1]][[1]][[1]][[1]][[1]][[5]]$y1 = pos

# Legend key height ?
leg[[1]][[1]][[1]][[1]]$heights = unit.c(rep(unit(0, "mm"), 3),
                                         unit(1, "npc"),
                                         unit(0, "mm"))
# Legend height
leg[[1]][[1]]$heights[[3]] = sum(rep(unit(0, "mm"), 3),
                                 unit(1, "npc"),
                                 unit(0, "mm"))

# grid.draw(leg)  # Check on heights and y values

# gtable_show_layout(gt) # Manually locate position of legend in layout
gt.new = gtable_add_grob(gt, leg, t = 7, l = 9)

# Draw it
grid.newpage()
grid.draw(gt.new)

【讨论】:

我在尝试遵循此示例时遇到了invalid 'layout.pos.row' 错误。你以前见过这个吗? @spacedSparking 在这种情况下,当“t”和/或“l”超出给定 gtable 的可能值时,通常会发生错误。但是,该代码对我有用——我使用的是 R v3.5.1、ggplot2 v3.1.0、gtable v0.2.0。我猜你使用的是旧版本的 ggplot2。【参考方案2】:

这似乎很棘手,我得到的最接近的是这个,

## panel height is 1null, so we work it out by subtracting the other heights from 1npc
## and 1line for the default plot margins

panel_height = unit(1,"npc") - sum(ggplotGrob(plot)[["heights"]][-3]) - unit(1,"line")
plot + guides(fill= guide_colorbar(barheight=panel_height))

不幸的是,垂直对齐有点偏离。

【讨论】:

Pretty durned close.... 可能需要更多调整,但我继续将其标记为已回答。谢谢指点。 有什么方法可以防止输出空图?当我运行 panel_height 线时,会出现一个空图。不理想,因为它会导致保存该空图。 嗨,这真的还是我们能做的最好的吗?

以上是关于如何使 ggplot2 中的图例与我的情节高度相同?的主要内容,如果未能解决你的问题,请参考以下文章

避免使用 facet_wrap 从 ggplot 进行情节转换中的图例重复

如何使用ggplot2编辑图例的位置

ggplot2:顶部图例键符号大小随图例键标签而变化

ggplot2:如何显示图例[重复]

用ggplot2添加图例[重复]

如何在ggplot2的图例中斜体化一个类别