rhelp.20.trevva at spamgourmet.com
2008-Feb-18 09:53 UTC
[R] Plotting a legend outside the figure - units
Dear R gurus, I am trying to plot a legend in the margins of a figure. The basic idea is to have two (or more) plots on the same figure, but then to have a common legend at the bottom of the plot. The approach that I have taken is to setup the figures, then do a "dummy" plot of the legend to determine the height of the legend box (ie from the value returned by the legend() command). I then use this height to adjust the outer margin of the plot to make sufficient space for the legend. After plotting the actual plots, I then finally plot the legend, moving it down to the bottom using the inset option in legend(). The problem is a question of units. I have not been able to find what units legend() returns anywhere in the documentation (ie in rect$h) - I've made the asumption that its inches, but that may not necessarily be correct. Similarly, the inset option to legend() requires units equal to a fraction of the plot size, but I'm not exactly sure how to make that line up with what I get out of legend(). Suggestions and insights most welcome! Code follows at the bottom. Cheers, Mark ----- graphics.off() #First set number of plots par(mfrow=c(2,1)) #Generate the legend once to get the height leg <- legend("bottom",legend=c("Item A","Item B"),horiz=TRUE,pch=c(1,2), col=c("red","blue"),plot=FALSE,trace=TRUE) par(oma=c(5,4,4,2)+0.1,mar=c(0,0,0,0),xpd=NA) #Add space at the bottom for the legend bottom.spacing <- par("omi") + c(leg$rect$h,0,0,0) par(omi=bottom.spacing) x <- runif(100) y <- runif(100) z <- rnorm(100) plot(x,y,xaxt="n",xlim=c(0,1),xlab="",pch=1,col="red") plot(y,z,xlim=c(0,1),pch=2,col="blue") #Actually plot legend this time - inset value is done manually by trial #and error, but obviosuly I'd rather have this done intelligently legend("bottom",legend=c("Item A","Item B"),horiz=TRUE,pch=c(1,2), col=c("red","blue"),inset=c(0,-0.475))
rhelp.20.trevva at spamgourmet.com wrote:> Dear R gurus, > > I am trying to plot a legend in the margins of a figure. The basic idea is to have two (or more) plots on the same figure, but then to have a common legend at the bottom of the plot. The approach that I have taken is to setup the figures, then do a "dummy" plot of the legend to determine the height of the legend box (ie from the value returned by the legend() command). I then use this height to adjust the outer margin of the plot to make sufficient space for the legend. After plotting the actual plots, I then finally plot the legend, moving it down to the bottom using the inset option in legend(). > > The problem is a question of units. I have not been able to find what units legend() returns anywhere in the documentation (ie in rect$h) - I've made the asumption that its inches, but that may not necessarily be correct. Similarly, the inset option to legend() requires units equal to a fraction of the plot size, but I'm not exactly sure how to make that line up with what I get out of legend(). >The rect values are returned in data coordinates, not inches. So if you plot(1, 1000000), you'll get a legend with x coordinate near 1, and y coordinate near 1000000. You specify the inset values in fractions of the plot region. par("usr") can give the coordinates of the plot region in data coordinates if you want to translate. Duncan Murdoch> Suggestions and insights most welcome! Code follows at the bottom. > > Cheers, > > Mark > ----- > > graphics.off() > #First set number of plots > par(mfrow=c(2,1)) > > #Generate the legend once to get the height > leg <- legend("bottom",legend=c("Item A","Item B"),horiz=TRUE,pch=c(1,2), > col=c("red","blue"),plot=FALSE,trace=TRUE) > > par(oma=c(5,4,4,2)+0.1,mar=c(0,0,0,0),xpd=NA) > > #Add space at the bottom for the legend > bottom.spacing <- par("omi") + c(leg$rect$h,0,0,0) > par(omi=bottom.spacing) > > x <- runif(100) > y <- runif(100) > z <- rnorm(100) > plot(x,y,xaxt="n",xlim=c(0,1),xlab="",pch=1,col="red") > plot(y,z,xlim=c(0,1),pch=2,col="blue") > > #Actually plot legend this time - inset value is done manually by trial > #and error, but obviosuly I'd rather have this done intelligently > legend("bottom",legend=c("Item A","Item B"),horiz=TRUE,pch=c(1,2), > col=c("red","blue"),inset=c(0,-0.475)) > > ______________________________________________ > R-help at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. >