Monthly Archives: September 2012

par(“usr”) is my new friend for inserting legends in plots!

I’ve decided to write a post about a solution to a problem I’ve been dealing with, pretty much since I started using R to make nice graphics 5+ years ago. Many times while exploring datasets, I’d want to make many similar plots (such as xy scatterplots) but with different variables for the x and y axes. This was all fine and well, but when It came time to annotate the graph with legends, text, etc., I would have to manual adjust the positions for the legend and text for each plot so that it wouldn’t cover up the data, the text would always plot in the upper left corner, etc.

I’ve always known about the “usr” parameter in the par() function (I even used it once in the a previous post about plotting dates along the x-axis), but I never really investigated it fully. Well, recently I had to make many xy scatterplots, and wanted to add a legend in the same location for each plot. A prefect application for “usr”!

For this example I will show my solution to always having the legend in the lower right corner (since I knew ahead of time the data would not fall in that region). For a full explanation of the par()“usr” parameter and par() function in general, check out the ?par() next time you are in R. I’m sure there are many different applications!

I first will create some fake data so that I can make a xy scatterplot and plot it up. Next, I’ll use the par("usr") to get the range of the x and y axes in the plot.  Then I will treat the legend as a variable to access the properties of the legend object (namely the width and the height of the legend rectangle).  Finally, I will anchor the legend in the lower right corner of the plot using information from the "lgd" variable and par("usr")!:

# Create fake data
x1 <- seq(0.1, 10, 0.5) + rnorm (length(seq(0.1, 10, 0.5)), 0.25)
y1 <- seq(0.1, 10, 0.5) + rnorm (length(seq(0.1, 10, 0.5)), 0.25)

# Plot
plot(x1, y1, pch = 20, cex = 2.5)

# Determine plot boundaries, in units of the data
xmin <- par("usr")[1]
xmax <- par("usr")[2]
ymin <- par("usr")[3]
ymax <- par("usr")[4]

#Now determine the size of the legend you would like to plot.  Right now the exact
#location is not important, we just want to know the dimension!  Note that we are
# treating the lengend as a variable and we are NOT plotting the legend on the figure!
lgd <- legend(x = mean(c(xmin,xmax)), y =  mean(c(ymin,ymax)),
c("Your data name"), pch = c(20), col = c("black"), plot = F)

# Add legend in the lower right corner:
legend(x = xmax - lgd$rect$w, y =  ymin + lgd$rect$h,
c("Your data name"), pch = c(20), col = c("black"), plot = T)

This has turned out to be a huge time saver, especially when I need to produce lots of quick plots with lots of different data!

“Automated” placement of the legend exactly in the lower right corner.