简体   繁体   English

Plot 是基本图形绘图区域之外的图例?

[英]Plot a legend outside of the plotting area in base graphics?

As the title says: How can I plot a legend outside the plotting area when using base graphics?正如标题所说:使用基本图形时,如何在绘图区域之外创建一个图例?

I thought about fiddling around with layout and produce an empty plot to only contain the legend, but I would be interested in a way using just the base graph facilities and eg, par(mar = ) to get some space on the right of the plot for the legend.我考虑过摆弄layout并生成一个空的 plot 以仅包含图例,但我会对仅使用基本图形工具的方法感兴趣,例如par(mar = )在 plot 右侧获得一些空间为传奇。


Here an example:这里有一个例子:

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

produces:产生:

替代文字

But as said, I would like the legend to be outside the plotting area (eg, to the right of the graph/plot.但如前所述,我希望图例位于绘图区域之外(例如,在图形/绘图的右侧。

No one has mentioned using negative inset values for legend . 没有人提到对legend使用负inset值。 Here is an example, where the legend is to the right of the plot, aligned to the top (using keyword "topright" ). 这是一个示例,其中图例位于图的右侧,并与顶部对齐(使用关键字"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")

The first value of inset=c(-0.2,0) might need adjusting based on the width of the legend. inset=c(-0.2,0)的第一个值可能需要根据图例的宽度进行调整。

legend_right

Maybe what you need is par(xpd=TRUE) to enable things to be drawn outside the plot region. 也许您需要的是par(xpd=TRUE)来使事物能够在绘图区域之外绘制。 So if you do the main plot with bty='L' you'll have some space on the right for a legend. 因此,如果使用bty='L'进行主图绘制,则bty='L'的右侧将有一些空间。 Normally this would get clipped to the plot region, but do par(xpd=TRUE) and with a bit of adjustment you can get a legend as far right as it can go: 通常,这会被裁剪到绘图区域,但是可以执行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))

Another solution, besides the ondes already mentioned (using layout or par(xpd=TRUE) ) is to overlay your plot with a transparent plot over the entire device and then add the legend to that. 除了已经提到的ondes(使用layoutpar(xpd=TRUE) )之外,另一种解决方案是在整个设备上用透明图覆盖您的图,然后在其中添加图例。

The trick is to overlay a (empty) graph over the complete plotting area and adding the legend to that. 诀窍是在整个绘图区域上覆盖一个(空)图形,并在其中添加图例。 We can use the par(fig=...) option. 我们可以使用par(fig=...)选项。 First we instruct R to create a new plot over the entire plotting device: 首先,我们指示R在整个绘图设备上创建一个新绘图:

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

Setting oma and mar is needed since we want to have the interior of the plot cover the entire device. 需要设置omamar ,因为我们想让绘图的内部覆盖整个设备。 new=TRUE is needed to prevent R from starting a new device. 需要new=TRUE来防止R启动新设备。 We can then add the empty plot: 然后我们可以添加空图:

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

And we are ready to add the legend: 现在我们准备添加图例:

legend("bottomright", ...)

will add a legend to the bottom right of the device. 将在设备的右下角添加图例。 Likewise, we can add the legend to the top or right margin. 同样,我们可以将图例添加到顶部或右边距。 The only thing we need to ensure is that the margin of the original plot is large enough to accomodate the legend. 我们唯一需要确保的是原始图的边距足够大以容纳图例。

Putting all this into a function; 把所有这些都放到一个函数中;

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(...)
}

And an example. 还有一个例子。 First create the plot making sure we have enough space at the bottom to add the legend: 首先创建图,确保底部有足够的空间来添加图例:

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

Then add the legend 然后添加图例

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

Resulting in: 导致:

示例图的上边显示图例

I like to do it like this: 我喜欢这样:

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

在此处输入图片说明

The only tweaking required is in setting the right margin to be wide enough to accommodate the legend. 唯一需要进行的调整就是将正确的边距设置得足够宽以容纳图例。

However, this can also be automated: 但是,这也可以自动化:

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

在此处输入图片说明

Sorry for resurrecting an old thread, but I was with the same problem today. 对不起,我要复活旧线程,但是今天我遇到了同样的问题。 The simplest way that I have found is the following: 我发现的最简单的方法如下:

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

Found here: http://www.harding.edu/fmccown/R/ 在这里找到: http : //www.harding.edu/fmccown/R/

Recently I found very easy and interesting function to print legend outside of the plot area where you want. 最近,我发现了一个非常简单有趣的功能,可以在想要的绘图区域之外打印图例。

Make the outer margin at the right side of the plot. 在图的右侧绘制外边缘。

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

Create a plot 创建图

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

Add legend and just use locator(1) function as like below. 添加图例,只需使用locator(1)函数,如下所示。 Then you have to just click where you want after load following script. 然后,您只需在加载以下脚本后单击所需的位置即可。

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

Try it 试试吧

I can offer only an example of the layout solution already pointed out. 我只能提供已经指出的布局解决方案的示例。

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

一张丑陋的照片:S

Adding another simple alternative that is quite elegant in my opinion. 在我看来,添加另一个非常优雅的简单替代方案。

Your plot: 您的情节:

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: 传说:

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

Result: 结果:

带有图例的图片

Here only the second line of the legend was added to your example. 这里,图例的第二行仅添加到您的示例中。 In turn: 反过来:

  • inset=c(0,1) - moves the legend by fraction of plot region in (x,y) directions. inset=c(0,1) -在(x,y)方向上按图例区域的比例移动图例。 In this case the legend is at "bottomright" position. 在这种情况下,图例位于"bottomright"位置。 It is moved by 0 plotting regions in x direction (so stays at "right") and by 1 plotting region in y direction (from bottom to top). 它在x方向上移动0个绘图区域(因此保持在“右侧”),并在y方向上(从底部到顶部)移动1个绘图区域。 And it so happens that it appears right above the plot. 碰巧它出现在情节上方。
  • xpd=TRUE - let's the legend appear outside of plotting region. xpd=TRUE让图例出现在绘图区域之外。
  • horiz=TRUE - instructs to produce a horizontal legend. horiz=TRUE指示生成水平图例。
  • bty="n" - a style detail to get rid of legend bounding box. bty="n" -摆脱图例边界框的样式细节。

Same applies when adding legend to the side: 将图例添加到侧面时同样适用:

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

Here we simply adjusted legend positions and added additional margin space to the right side of the plot. 在这里,我们只是调整了图例位置,并在图的右侧添加了额外的边距空间。 Result: 结果:

图例2

You could do this with the Plotly R API , with either code, or from the GUI by dragging the legend where you want it. 您可以使用Plotly R API (使用代码)或通过将GUI拖动到所需的图例来执行此操作。

Here is an example. 这是一个例子。 The graph and code are also 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)

You can position the legend outside of the graph by assigning one of the x and y values to either 100 or -100. 通过将x和y值之一分配给100或-100,可以将图例放置在图形之外。

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

Here are the other options: 以下是其他选项:

  • list("x" = 100, "y" = 0) for Outside Right Bottom list("x" = 100, "y" = 0)表示外部右下角
  • list("x" = 100, "y"= 1) Outside Right Top list("x" = 100, "y"= 1)右上角外
  • list("x" = 100, "y" = .5) Outside Right Middle list("x" = 100, "y" = .5)右外中
  • list("x" = 0, "y" = -100) Under Left list("x" = 0, "y" = -100)左下方
  • list("x" = 0.5, "y" = -100) Under Center list("x" = 0.5, "y" = -100)居中
  • list("x" = 1, "y" = -100) Under Right list("x" = 1, "y" = -100)在右下方

Then the response. 然后回应。

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

Plotly returns a URL with your graph when you make a call. 拨打电话时,使用图形绘制出一个URL。 You can access that more quickly by calling browseURL(response$url) so it will open your graph in your browser for you. 您可以通过调用browseURL(response$url)更快地访问它,这样它将为您打开浏览器中的图形。

url = response$url
filename = response$filename

That gives us this graph. 这给了我们这张图。 You can also move the legend from within the GUI and then the graph will scale accordingly. 您也可以从GUI内移动图例,然后图形将相应缩放。 Full disclosure: I'm on the Plotly team. 全面披露:我在Plotly团队中。

图边的图例

Try layout() which I have used for this in the past by simply creating an empty plot below, properly scaled at around 1/4 or so and placing the legend parts manually in it. 尝试在过去使用过的layout() ,只需在下面创建一个空图,适当地缩放到1/4左右,然后手动将图例部分放入其中即可。

There are some older questions here about legend() which should get you started. 这里有一些有关legend()较旧问题,应该可以帮助您入门。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM