Another solution, besides the ones 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: