Search code examples
rformatlegendlegend-properties

Padding Around Legend when using Pch in Base R


Just a minor question. I am trying to make a legend for the following plot.

# fitting the linear model
iris_lm = lm(Petal.Length ~ Sepal.Length, data = iris)
summary(iris_lm)

# calculating the confidence interval for the fitted line
preds = predict(iris_lm, newdata = data.frame(Sepal.Length = seq(4,8,0.1)),
                  interval = "confidence")

# making the initial plot
par(family = "serif")
plot(Petal.Length ~ Sepal.Length, data = iris, col = "darkgrey",
     family = "serif", las = 1, xlab = "Sepal Length", ylab = "Pedal Length")

# shading in the confidence interval
polygon(
  c(seq(8,4,-0.1), seq(4,8,0.1)), # all of the necessary x values
  c(rev(preds[,3]), preds[,2]), # all of the necessary y values
  col = rgb(0.2745098, 0.5098039, 0.7058824, 0.4), # the color of the interval
  border = NA # turning off the border
)

# adding the regression line
abline(iris_lm, col = "SteelBlue")

# adding a legend
legend("bottomright", legend = c("Fitted Values", "Confidence Interval"),
       lty = c(1,0))

Here's the output so far:

enter image description here

My goal is to put a box in the legend next to the "Confidence Interval" tab, and color it in the same shade that it is in the picture. Naturally, I thought to use the pch parameter. However, when I re-run my code with the additional legend option pch = c(NA, 25), I get the following:

enter image description here

It is not super noticeable, but if you look closely at the padding on the left margin of the legend, it actually has decreased, and the edge of the border is now closer to the line than I would like. Is there any way to work around this?


Solution

  • That's a curious behavior in legend(). I'm sure someone will suggest a ggplot2 alternative. However, legend() does offer a solution. This solution calls the function without plotting anything to capture the dimensions of the desired rectangle. The legend is then plotted with the elements you really want but no enclosing box (bty = "n"). The desired rectangle is added explicitly. I assume you mean pch = 22 to get the filled box symbol. I added pt.cex = 2 to make it a bit larger.

    # Capture the confidence interval color, reusable variables
      myCol <- rgb(0.2745098, 0.5098039, 0.7058824, 0.4)
      legText <- c("Fitted Values", "Confidence Interval")
    
    # Picking it up from 'adding a legend'
      ans <-  legend("bottomright", lty = c(1,0), legend = legText, plot = F)
      r <- ans$rect
      legend("bottomright", lty = c(1,0), legend = legText, pch = c(NA,22),
        pt.bg = myCol, col = c(1, 0), pt.cex = 2, bty = "n")
    
    # Draw the desired box
      rect(r$left, r$top - r$h, r$left + r$w, r$top)
    

    By the way, I don't think this will work without further tweaking if you place the legend on the left side.