[R] How to plot a legend centered only on the x axis

Marc Schwartz marc_schwartz at me.com
Thu May 11 21:19:12 CEST 2017


> On May 11, 2017, at 1:36 PM, Antonio Silva <aolinto.lst at gmail.com> wrote:
> 
> Hello r-users
> 
> I want to plot some barplots inside a looping with the legend placed
> outside the plotting area.
> 
> No matter the number of bars I want the legend to be placed centered on the
> x-axis.
> 
> See the example below
> 
> for(i in 1:10) {
> var_1 <- sample(1000:100000,sample(3:8,1))
> ymax <- max(var_1)
> b<-barplot(var_1,col="blue")
> var_2 <- sample(1000:ymax,length(var_1))
> lines(rowSums(b),var_2,type="o",col="red",pch=16)
> par(xpd=TRUE)
> legend(*1.1*
> ,ymax*-0.072,c("var_1","var_2"),horiz=T,cex=1.3,bty="n",pch=c(15,16),col=c("blue","red"),lty=c(0,1),lwd=c(0,2),pt.cex=2)
> readline(prompt="Press [enter] to continue")
> }
> 
> What I should use as x position in legend(x,y, ...), instead of *1.1*, to
> have the legend centered on the x-axis?
> 
> I would love to use something like legend(x="center",y=ymax*-0.072, ... but
> it did not worked.co
> 
> I appreciate any suggestions. Best regards.
> 
> Antonio


Hi,

There is a level of magic that goes into the legend() code to determine the placement of the legend. You can take the time to review the code for the function, noting how, internally, the location of the box that contains the legend is determined.

Somebody may have an easier way to do this, but one approach is to first call legend() but set 'plot = FALSE' and obtain the return values of the function for use in a second call that will draw the legend in the position you desire.


Here is some basic information:

# Draw the initial barplot
barplot(1:5)

# Call legend() the first time, but don't draw it
# See ?legend for the Value section
# Use "bottom" to get the legend drawn in the center of the x axis, but it 
# will be within the plot region by default.
# Just save the 'rect' component of the returned value
BOX <- legend("bottom", legend = c("Label 1", "Label 2"), plot = FALSE)$rect

# This gives us the width and height of the box containing the legend
# as well as the x,y coordinates of the upper left hand corner
> BOX
$w
[1] 1.002451

$h
[1] 0.5872093

$left
[1] 2.598775

$top
[1] 0.5372093


Now, using BOX$left, which defines the x axis value for the left side of the legend box that is centered, we can call legend() a second time and adjust the y axis value of the legend to place it outside the plot region, below the plot. Just be sure that your second call to legend() is exactly the same as the first call, other than setting legend to FALSE in the first case. Any change in legend content between the two calls will alter the size and position of the enclosing box.

par(xpd = TRUE)
legend(BOX$left, y = -0.25, legend = c("Label 1", "Label 2"))


You can then adapt that basic approach to use in your code.

As an FYI, see ?par and note "usr", which defines the coordinates of the plot region. If desired, you can get the midpoint of the x axis using:

  mean(par("usr")[1:2])

Regards,

Marc Schwartz



More information about the R-help mailing list