r - ggplot : "size-robust" way to place horizontal legend at the bottom-right

标签 r ggplot2 legend

我试图在绘图区域外的右下角放置一个水平图例。
我意识到之前已经讨论过这个问题。然而,在一个漫长而令人沮丧的早晨之后,我无法找到一个“大小稳健”的解决方案。
以下是我找到的 3 个解决方案:

  • 当我设置 legend.positionbottom : 图例位于
    底部中心,但我无法使用legend.justification
  • 当我设置 legend.positionc(1,0) :图例位于
    右下角。但是,图例位于情节内。
  • 当我添加 plot.margin并推送 legend.position再向下:
    图例位于图的右下角和外部。但是,当我更改绘图区域的大小时,图例不再正确定位。

  • 第三个解决方案定位不正确:
    enter image description here enter image description here

    可重现代码:
    # Generate random data------
    
    sample.n = 50
    sample.data = data.frame(x = runif(sample.n,0,1), y = runif(sample.n,0,1), value = runif(sample.n,0,10))
    
    # Plot ------
    
    library(ggplot2)
    
    # Margins are fine. And If I change the size of the plotting area, the legend will always be bottom- centered
    # Problem: Can't push it to the right side  
    ggplot(sample.data, aes(x = x, y = y, color = value)) + geom_point() + 
      theme(legend.direction = "horizontal", legend.position = "bottom") 
    
    # Pushed to the bottom-right Successfully 
    # Problem: Legend inside the plot
    ggplot(sample.data, aes(x = x, y = y, color = value)) + geom_point() + 
      theme(legend.direction = "horizontal",legend.position = c(1,0)) # Problem: inside plot 
    
    # Placed at the bottom-right corner outside the plot region 
    # Problem: If I change the size of the plotting region, the legend will not be cornred
    ggplot(sample.data, aes(x = x, y = y, color = value)) + geom_point() + 
      theme(legend.direction = "horizontal", legend.position = c(0.9,-0.2),  
            plot.margin = unit(c(1, 1, 5, 1), "lines"))  
    

    主题传奇的文档:

    legend.position the position of legends ("none", "left", "right", "bottom", "top", or two-element numeric vector)

    legend.justification anchor point for positioning legend inside plot ("center" or two-element numeric vector)

    最佳答案

    编辑 使用 2.2.0,可以使用 legend.justification 将图例推到右侧和 legend.margin在主题中。

    # Generate random data------
    
    sample.n = 50
    sample.data = data.frame(x = runif(sample.n,0,1), y = runif(sample.n,0,1), value = runif(sample.n,0,10))
    
    # Plot ------
    
    library(ggplot2)
    library(gtable)
    library(grid)
    
    p = ggplot(sample.data, aes(x = x, y = y, color = value)) + geom_point() + 
      theme(legend.direction = "horizontal", legend.position = "bottom",
              legend.box.background = element_rect(colour = "black"))
    
    p + theme(legend.justification = "right",
              legend.margin = margin(t = 2, r = 0, b = 2, l = 2, unit = "mm"))
    

    enter image description here

    对于它的值(value),我保留了原始答案,但已更新为 ggplot 2.2.0 版。

    我在这里所做的是从图中提取图例,将图例包装在视口(viewport)中,使视口(viewport)位于右侧,将图例放回图中,并删除原始图例。
    # Generate random data------
    
    sample.n = 50
    sample.data = data.frame(x = runif(sample.n,0,1), y = runif(sample.n,0,1), value = runif(sample.n,0,10))
    
    # Plot ------
    
    library(ggplot2)
    library(gtable)
    library(grid)
    
    p = ggplot(sample.data, aes(x = x, y = y, color = value)) + geom_point() + 
      theme(legend.direction = "horizontal", legend.position = "bottom")
    
    # Get the ggplot grob
    g = ggplotGrob(p)
    
    # Get the legend
    index = which(g$layout$name == "guide-box")
    leg = g$grobs[[index]]
    
    # Wrap the legend in a viewport
    leg$vp = viewport(x = unit(1, "npc"), width = sum(leg$widths), just = "right")
    
    ### Put the legend back into the plot
         # First, get the current location of the legend
    pos = g$layout[index, ]
    g = gtable_add_grob(g, leg, t = pos$t, l = pos$l)
    
    # Remove the original legend
    g$grobs <- g$grobs[-index]
    g$layout <- g$layout[-index, ]
    
    # Draw the chart
    grid.newpage()
    grid.draw(g)
    

    enter image description here

    请注意,图例已移至右侧,但图例的右边缘与绘图面板的右边缘并不完全对齐。这是因为图例具有内部边距。图例本身有一个边距,但该边距设置为 0 毫米。要使图例与绘图面板对齐,需要更多的摆弄。在接下来的内容中,内部边距(和图例边距)设置为 0。此外,图例和图例的内部部分被包裹在右对齐的视口(viewport)中。
    # Get the ggplot grob
    g = ggplotGrob(p)
    
    # Get the legend
    index = which(g$layout$name == "guide-box")
    leg = g$grobs[[index]]
    
    # Remove the legend right margin and an internal margin
    leg$widths[4] = unit(0, "mm")
    leg$grobs[[1]]$widths[5] = unit(0, "mm")
    
    # Wrap the legend in a viewport
    leg$vp = viewport(x = unit(1, "npc"), width = sum(leg$widths), just = "right")
    
    # Wrap the internal part of the legend in a right justified viewport
    leg$grobs[[1]]$vp = viewport(x = unit(1, "npc"), width = sum(leg$grobs[[1]]$widths), just = "right")
    
    ### Put the legend back into the plot
         # First, get the current location of the legend
    pos = g$layout[index, ]
    g = gtable_add_grob(g, leg, t = pos$t, l = pos$l)
    
    # Remove the original legend
    g$grobs <- g$grobs[-index]
    g$layout <- g$layout[-index, ]
    
    # Draw the chart
    grid.newpage()
    grid.draw(g)
    

    enter image description here

    关于r - ggplot : "size-robust" way to place horizontal legend at the bottom-right,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38222688/

    相关文章:

    r - 有没有办法用 sparklyr 处理嵌套数据?

    python - 带有 twinx() : how to add to legend? 的辅助轴

    r - ggplot2 R 上的连续到离散图例

    r - 如何使 geom_text() 与 geom_segment() 在 log-lin 尺度上平行?

    r - ggplot 两个阴影区域 geom_area

    r - 如何在R中手动更改ggplot2图例的文本颜色?

    r - ggpairs 更改轴标签字体大小

    r - 将函数应用于多个数据表

    r - 如何在远程服务器上使用R studio

    r - 在 ggplot2 中创建计数频率的直方图