首页 文章

在基本图形中绘制绘图区域外的图例?

提问于
浏览
148

正如 Headers 所说: How can I plot a legend outside the plotting area when using base graphics?

我想要摆弄 layout 并制作一个只包含图例的空图,但我会对使用基本图形工具的方式感兴趣,例如, par(mar = ) 在图例右侧的图例中获得一些空间 .


这是一个例子:

plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2))
lines(1:3, rnorm(3), pch = 2, lty = 2, type="o")
legend(1,-1,c("group A", "group B"), pch = c(1,2), lty = c(1,2))

生产环境 :

alt text

但如上所述,我希望图例位于绘图区域之外(例如,图表/图表的右侧) .

10 回答

  • 1

    也许你需要的是 par(xpd=TRUE) ,以便能够在情节区域之外绘制东西 . 因此,如果您使用 bty='L' 进行主图,则右侧会有一些空间用于图例 . 通常这会被剪切到绘图区域,但是做一些调整,你可以得到一个尽可能正确的传奇:

    set.seed(1) # just to get the same random numbers
     par(xpd=FALSE) # this is usually the default
    
     plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2), bty='L')
     # this legend gets clipped:
     legend(2.8,0,c("group A", "group B"), pch = c(1,2), lty = c(1,2))
    
     # so turn off clipping:
     par(xpd=TRUE)
     legend(2.8,-1,c("group A", "group B"), pch = c(1,2), lty = c(1,2))
    
  • 0

    没人提到 legend 使用负 inset 值 . 下面是一个示例,其中图例位于图的右侧,与顶部对齐(使用关键字 "topright" ) .

    # Random data to plot:
    A <- data.frame(x=rnorm(100, 20, 2), y=rnorm(100, 20, 2))
    B <- data.frame(x=rnorm(100, 21, 1), y=rnorm(100, 21, 1))
    
    # Add extra space to right of plot area; change clipping to figure
    par(mar=c(5.1, 4.1, 4.1, 8.1), xpd=TRUE)
    
    # Plot both groups
    plot(y ~ x, A, ylim=range(c(A$y, B$y)), xlim=range(c(A$x, B$x)), pch=1,
                   main="Scatter plot of two groups")
    points(y ~ x, B, pch=3)
    
    # Add legend to top right, outside plot region
    legend("topright", inset=c(-0.2,0), legend=c("A","B"), pch=c(1,3), title="Group")
    

    inset=c(-0.2,0) 的第一个值可能需要根据图例的宽度进行调整 .

    legend_right

  • 21

    除了已经提到的ondes(使用 layoutpar(xpd=TRUE) )之外,另一个解决方案是在整个设备上使用透明图覆盖您的绘图,然后将图例添加到该图中 .

    诀窍是在整个绘图区域上覆盖(空)图形并将图例添加到该图形 . 我们可以使用 par(fig=...) 选项 . 首先,我们指示R在整个绘图设备上创建一个新的图:

    par(fig=c(0, 1, 0, 1), oma=c(0, 0, 0, 0), mar=c(0, 0, 0, 0), new=TRUE)
    

    需要设置 omamar ,因为我们希望绘图的内部覆盖整个设备 . 需要 new=TRUE 来阻止R启动新设备 . 然后我们可以添加空图:

    plot(0, 0, type='n', bty='n', xaxt='n', yaxt='n')
    

    我们准备添加传奇:

    legend("bottomright", ...)
    

    将在设备的右下角添加一个图例 . 同样,我们可以将图例添加到顶部或右边距 . 我们唯一需要确保的是原始图的边距足够大以容纳图例 .

    把所有这些都放到一个功能中;

    add_legend <- function(...) {
      opar <- par(fig=c(0, 1, 0, 1), oma=c(0, 0, 0, 0), 
        mar=c(0, 0, 0, 0), new=TRUE)
      on.exit(par(opar))
      plot(0, 0, type='n', bty='n', xaxt='n', yaxt='n')
      legend(...)
    }
    

    还有一个例子 . 首先创建绘图,确保底部有足够的空间来添加图例:

    par(mar = c(5, 4, 1.4, 0.2))
    plot(rnorm(50), rnorm(50), col=c("steelblue", "indianred"), pch=20)
    

    然后添加图例

    add_legend("topright", legend=c("Foo", "Bar"), pch=20, 
       col=c("steelblue", "indianred"),
       horiz=TRUE, bty='n', cex=0.8)
    

    导致:

    Example figure shown legend in top margin

  • 3

    很抱歉复活旧线程,但今天我遇到了同样的问题 . 我找到的最简单的方法如下:

    # Expand right side of clipping rect to make room for the legend
    par(xpd=T, mar=par()$mar+c(0,0,0,6))
    
    # Plot graph normally
    plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2))
    lines(1:3, rnorm(3), pch = 2, lty = 2, type="o")
    
    # Plot legend where you want
    legend(3.2,1,c("group A", "group B"), pch = c(1,2), lty = c(1,2))
    
    # Restore default clipping rect
    par(mar=c(5, 4, 4, 2) + 0.1)
    

    在此处找到:http://www.harding.edu/fmccown/R/

  • 94

    我喜欢这样做:

    par(oma=c(0, 0, 0, 5))
    plot(1:3, rnorm(3), pch=1, lty=1, type="o", ylim=c(-2,2))
    lines(1:3, rnorm(3), pch=2, lty=2, type="o")
    legend(par('usr')[2], par('usr')[4], bty='n', xpd=NA,
           c("group A", "group B"), pch=c(1, 2), lty=c(1,2))
    

    enter image description here

    唯一需要调整的是将右边距设置得足够宽以容纳图例 .

    但是,这也可以自动化:

    dev.off() # to reset the graphics pars to defaults
    par(mar=c(par('mar')[1:3], 0)) # optional, removes extraneous right inner margin space
    plot.new()
    l <- legend(0, 0, bty='n', c("group A", "group B"), 
                plot=FALSE, pch=c(1, 2), lty=c(1, 2))
    # calculate right margin width in ndc
    w <- grconvertX(l$rect$w, to='ndc') - grconvertX(0, to='ndc')
    par(omd=c(0, 1-w, 0, 1))
    plot(1:3, rnorm(3), pch=1, lty=1, type="o", ylim=c(-2, 2))
    lines(1:3, rnorm(3), pch=2, lty=2, type="o")
    legend(par('usr')[2], par('usr')[4], bty='n', xpd=NA,
           c("group A", "group B"), pch=c(1, 2), lty=c(1, 2))
    

    enter image description here

  • 7

    我只能提供已经指出的布局解决方案的示例 .

    layout(matrix(c(1,2), nrow = 1), widths = c(0.7, 0.3))
    par(mar = c(5, 4, 4, 2) + 0.1)
    plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2))
    lines(1:3, rnorm(3), pch = 2, lty = 2, type="o")
    par(mar = c(5, 0, 4, 2) + 0.1)
    plot(1:3, rnorm(3), pch = 1, lty = 1, ylim=c(-2,2), type = "n", axes = FALSE, ann = FALSE)
    legend(1, 1, c("group A", "group B"), pch = c(1,2), lty = c(1,2))
    

    an ugly picture :S

  • 7

    最近我发现在你想要的情节区域之外打印图例非常简单有趣 .

    在图的右侧创建外边距 .

    par(xpd=T, mar=par()$mar+c(0,0,0,5))
    

    创建一个情节

    plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2))
    lines(1:3, rnorm(3), pch = 2, lty = 2, type="o")
    

    添加图例,只需使用locator(1)函数,如下所示 . 然后,您必须在加载以下脚本后单击所需的位置 .

    legend(locator(1),c("group A", "group B"), pch = c(1,2), lty = c(1,2))
    

    试试吧

  • 124

    您可以使用Plotly R API,使用任一代码执行此操作,也可以通过将图例拖动到所需位置来从GUI执行此操作 .

    这是一个例子 . 图表和代码也是here .

    x = c(0,1,2,3,4,5,6,7,8) 
    y = c(0,3,6,4,5,2,3,5,4) 
    x2 = c(0,1,2,3,4,5,6,7,8) 
    y2 = c(0,4,7,8,3,6,3,3,4)
    

    您可以通过将x和y值中的一个指定为100或-100来将图例定位在图表外部 .

    legendstyle = list("x"=100, "y"=1)
    layoutstyle = list(legend=legendstyle)
    

    以下是其他选项:

    外侧右下方

    • list("x" = 100, "y" = 0)

    • list("x" = 100, "y"= 1) 右上方

    • list("x" = 100, "y" = .5) 外右中

    • list("x" = 0, "y" = -100) 在左下方

    • list("x" = 0.5, "y" = -100) 在中心下

    • list("x" = 1, "y" = -100) 右下

    然后回应 .

    response = p$plotly(x,y,x2,y2, kwargs=list(layout=layoutstyle));

    当您拨打电话时,Plotly会在您的图表中返回一个网址 . 您可以通过调用 browseURL(response$url) 来更快地访问它,这样它就会在您的浏览器中打开您的图形 .

    url = response$url
    filename = response$filename
    

    这给了我们这张图 . 您还可以从GUI中移动图例,然后图形将相应缩放 . 完全披露:我在Plotly团队 .

    Legend on side of graph

  • 12

    尝试 layout() 过去我曾用过这个,只需在下面创建一个空图,在1/4左右正确缩放并手动将图例部分放入其中 .

    这里有一些关于 legend() 的旧问题应该可以帮到你 .

  • 12

    在我看来,添加另一个非常优雅的简单替代方案 .

    你的情节:

    plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2))
    lines(1:3, rnorm(3), pch = 2, lty = 2, type="o")
    

    传说:

    legend("bottomright", c("group A", "group B"), pch=c(1,2), lty=c(1,2),
           inset=c(0,1), xpd=TRUE, horiz=TRUE, bty="n"
           )
    

    结果:

    picture with legend

    这里只有图例的第二行添加到您的示例中 . 反过来:

    • inset=c(0,1) - 按(x,y)方向的绘图区域的分数移动图例 . 在这种情况下,图例位于 "bottomright" 位置 . 它在0方向上移动0个绘图区域(因此保持在"right"),并在y方向上绘制1个绘图区域(从下到上) . 它恰好出现在情节的正上方 .

    • xpd=TRUE - 让我们的图例出现在绘图之外区域 .

    • horiz=TRUE - 指示生成水平图例 .

    • bty="n" - 摆脱图例边界框的样式细节 .

    向侧面添加图例时同样适用:

    par(mar=c(5,4,2,6))
    plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2))
    lines(1:3, rnorm(3), pch = 2, lty = 2, type="o")
    
    legend("topleft", c("group A", "group B"), pch=c(1,2), lty=c(1,2),
           inset=c(1,0), xpd=TRUE, bty="n"
           )
    

    在这里,我们只是调整了图例位置,并在图的右侧添加了额外的边距空间 . 结果:

    picture with legend 2

相关问题