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

Hen*_*rik 168 plot r legend

正如标题所说:在使用基本图形时,如何在绘图区域外绘制图例?

我想要摆弄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))
Run Code Online (Sandbox Code Playgroud)

生产:

替代文字

但正如所说,我希望图例在绘图区域之外(例如,图表/图表的右侧).

Mik*_*e T 138

没有人使用负提到inset的值legend.下面是一个示例,其中图例位于图的右侧,与顶部对齐(使用关键字"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")
Run Code Online (Sandbox Code Playgroud)

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

legend_right

  • @Henrik没有它没有xpd = TRUE.另请注意,最好将xpd = TRUE设置为legend()函数的参数. (12认同)
  • 有时,必须将“xpd”设置为“TRUE”才能使负插入起作用。但有时不是。使用“barplot(...”中的命令“args.legend=list(x="bottom", horiz=TRUE, inset=-0.2)”,它似乎不需要“xpd=TRUE”,但只需`legend(x="bottom", horiz=TRUE, inset=-0.2)` 它似乎确实需要 `xpd=TRUE`。有什么见解吗?我只是在传递我的论点时感到困惑? (3认同)

Spa*_*man 105

也许你需要的是par(xpd=TRUE)让事情能够在情节区域之外被绘制出来.所以,如果你用主要情节做,bty='L'你会在右边有一些空间用于传说.通常这会被剪切到绘图区域,但是par(xpd=TRUE)通过一些调整,您可以获得尽可能正确的图例:

 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))
Run Code Online (Sandbox Code Playgroud)

  • 请注意,您可以将xpd直接传递给图例,这样您就不必担心之后重置par.另请参阅grconvertX和Y,以便以不依赖于您正在绘制的数据的限制的方式指定图例的位置. (32认同)
  • 因为这个问题和答案仍然非常流行,所以`par(xpd = NA)`更强大(即绘制到更多区域). (6认同)

Jan*_*aan 26

除了已经提到过的ondes(使用layout或者par(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)
Run Code Online (Sandbox Code Playgroud)

设置oma并且mar是必需的,因为我们希望绘图的内部覆盖整个设备.new=TRUE需要防止R启动新设备.然后我们可以添加空图:

plot(0, 0, type='n', bty='n', xaxt='n', yaxt='n')
Run Code Online (Sandbox Code Playgroud)

我们准备添加传奇:

legend("bottomright", ...)
Run Code Online (Sandbox Code Playgroud)

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

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

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(...)
}
Run Code Online (Sandbox Code Playgroud)

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

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

然后添加图例

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

导致:

示例图显示了上边距中的图例

  • 这里列表很棒.关于如何使用图形中的多个图表进行此工作的解释[此处](http://dr-k-lo.blogspot.com/2014/03/the-simplest-way-to-plot-legend-outside的.html). (2认同)

Mar*_*ves 15

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

# 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)
Run Code Online (Sandbox Code Playgroud)

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

  • 更好的是oldpar < - par(xpd = T,mar = par()$ mar + c(0,0,0,6))... par(oldpar)(参见par的帮助) (3认同)

jba*_*ums 15

我喜欢这样做:

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))
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

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

但是,这也可以自动化:

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))
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


Van*_*dka 9

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

在图的右侧创建外边距.

par(xpd=T, mar=par()$mar+c(0,0,0,5))
Run Code Online (Sandbox Code Playgroud)

创建一个情节

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")
Run Code Online (Sandbox Code Playgroud)

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

legend(locator(1),c("group A", "group B"), pch = c(1,2), lty = c(1,2))
Run Code Online (Sandbox Code Playgroud)

试试吧


Rom*_*rik 8

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

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))
Run Code Online (Sandbox Code Playgroud)

丑陋的画面:S


Kar*_*ius 7

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

您的情节:

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")
Run Code Online (Sandbox Code Playgroud)

传说:

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"
       )
Run Code Online (Sandbox Code Playgroud)

结果:

带有图例的图片

这里,图例的第二行仅添加到您的示例中。反过来:

  • inset=c(0,1)-在图例区域的(x,y)方向上移动图例。在这种情况下,图例"bottomright"就位。它在x方向上移动了0个绘图区域(因此保持在“右侧”),在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"
       )
Run Code Online (Sandbox Code Playgroud)

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

图例2