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

前端 未结 10 737
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-22 14:48

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

相关标签:
10条回答
  • 2020-11-22 15:39

    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/

    0 讨论(0)
  • 2020-11-22 15:39

    You could do this with the Plotly R API, with either code, or from the GUI by dragging the legend where you want it.

    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.

    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"= 1) Outside Right Top
    • list("x" = 100, "y" = .5) Outside Right Middle
    • list("x" = 0, "y" = -100) Under Left
    • list("x" = 0.5, "y" = -100) Under Center
    • list("x" = 1, "y" = -100) Under Right

    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. You can access that more quickly by calling browseURL(response$url) so it will open your graph in your browser for you.

    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. Full disclosure: I'm on the Plotly team.

    Legend on side of graph

    0 讨论(0)
  • 2020-11-22 15:41

    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.

    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. First we instruct R to create a new plot over the entire plotting device:

    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. new=TRUE is needed to prevent R from starting a new device. 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:

    Example figure shown legend in top margin

    0 讨论(0)
  • 2020-11-22 15:45

    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.

    There are some older questions here about legend() which should get you started.

    0 讨论(0)
提交回复
热议问题