rplot

How do you change the size of filled boxes of a legend made with base R (no ggplot)?


I have tried everything and searched everywhere (maybe I am exaggerating a bit), but I could not find a solution to this simple problem.

If I have this legend:

barplot(VADeaths)
legend("topright", rownames(VADeaths), fill = gray.colors(nrow(VADeaths)))

how can I decrease the size of the boxes? I am talking about the grayscale boxes on the left of the value labels. If I use cex it changes all elements of the legend; if I use pt.cex it does nothing...

example of the plot produced by the code with the interesting part highlighted


Solution

  • I'll answer with a "not really" for now, hoping that somebody else finds a trick I'm not aware of and proves me wrong :-)

    If you look at the source for legend, you'll see that the boxes are being created by an internally-defined rect2 function, and while its arguments are clear, exposing them is not really in the cards.

    Having said that, it's not too hard. I just dumped legend into a .R file and renamed the function legend2. I then changed one line (namely the dx= and dy= arguments) as

    @@ -1,4 +1,4 @@
    -legend <- function (x, y = NULL, legend, fill = NULL, col = par("col"),
    +legend2 <- function (x, y = NULL, legend, fill = NULL, col = par("col"),
         border = "black", lty, lwd, pch, angle = 45, density = NULL,
         bty = "o", bg = par("bg"), box.lwd = par("lwd"), box.lty = par("lty"),
         box.col = par("fg"), pt.bg = NA, cex = 1, pt.cex = cex, pt.lwd = lwd,
    
    @@ -269,7 +269,7 @@
             if (plot) {
                 if (!is.null(fill))
                     fill <- rep_len(fill, n.leg)
    -            rect2(left = xt, top = yt + ybox/2, dx = xbox, dy = ybox,
    +            rect2(left = xt, top = yt + ybox/2, dx = xbox*2, dy = ybox/2,
                     col = fill, density = density, angle = angle,
                     border = border)
             }
    

    and the plot changes from this

    barplot(VADeaths)
    legend("topright", rownames(VADeaths), fill = gray.colors(nrow(VADeaths)), bg = "white")
    

    basic barplot with default legend

    to this use of `legend2

    barplot(VADeaths)
    legend2("topright", rownames(VADeaths), fill = gray.colors(nrow(VADeaths)), bg = "white")
    

    same barplot with legend2 function

    I'm not saying that that's awesome, but the mechanism for changing it is relatively straight-forward. I could see adding arguments to the whole function that would generalize what you want, at the expense of maintaining a nearly identical version of graphics::legend.