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

时间:2010-10-14 10:01:44

标签: r plot 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))

产生

alt text

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

10 个答案:

答案 0 :(得分:131)

没有人提到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")

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

legend_right

答案 1 :(得分:100)

也许您需要的是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))

答案 2 :(得分:24)

除了已经提到的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 :(得分: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))

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

答案 4 :(得分:14)

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

# 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/

答案 5 :(得分:9)

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

在图的右侧绘制外边距。

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")

添加图例并使用定位器(1)功能,如下所示。然后,您只需在加载脚本后单击所需的位置。

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

试试吧

答案 6 :(得分: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))

an ugly picture :S

答案 7 :(得分:4)

您可以使用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) for Outside Right Bottom
  • list("x" = 100, "y"= 1) Outside Right Top
  • list("x" = 100, "y" = .5)外右中间
  • list("x" = 0, "y" = -100)左下
  • list("x" = 0.5, "y" = -100)在中心
  • list("x" = 1, "y" = -100) Under Right

然后回复。

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

答案 8 :(得分:4)

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

你的情节:

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"位置。它在x方向上由0个绘图区域移动(因此保持在&#34;右边#34;)并且在y方向上绘制区域(从下到上)。它恰好出现在情节的正上方。
  • 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

答案 9 :(得分:2)

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

这里有一些关于legend()的问题可以帮助您入门。