0
votes

I have a plot() where multiple colour shadings represent the same thing. I would like to add a legend that conveys this by having dual-coloured boxes (see example below). Is there any way to do this using legend() or a similar command? Alternatively, is there a way to identify the precise coordinates of these boxes so I can plot a polygon() triangle over it?

Note: legend() does return the coordinates of the outer box and the top left of each labels, but I am not sure if this is sufficient to calculate where the coloured boxes are.

How it should look like

2
Why do you have multiple colors for the same thing? - Molx
@Molx: To provide a simple example: Imagine a pie chart or stacked bar plot where you have a breakdown of a population by gender (male / female = blue / red) and income class (low/medium/high income = low/medium/high intensity colour). This results in a total of 6 combinations of colour and colour intensity. As you get a few more categories, it becomes desirable to have a legend that summarizes colour and intensity separately, rather than listing all possible combinations. - Rob Hall

2 Answers

1
votes

This is a bit of a hack, but you could put two legends on top of another. Unfortunately, there is no left triangle pch which would have been exactly as you wanted.

plot(1)
legend("bottomright",c("Label 1", "Label 2"),pch=22,col=c("red","blue"),pt.bg=c("red","blue"), pt.cex=1.8)
legend("bottomright",c("Label 1", "Label 2"),pch=21,col=c("green","orange"),pt.bg=c("green","orange"))

enter image description here

0
votes

A slightly dirty hack can allow you to get the legend() function to give you the necessary information. A smarter person than me would probably work out how legend() calculates box positioning and replicate this outside the function. Note that editing standard R functions is probably not recommended.

If you have not edited R functions yet, an easy (and temporary) way to access it, is typing

fix(legend)

Typing

rm(legend)

later will undo your changes.

Find this section that says fill <- rep and add the lines indicated by the comments:

    fillList <- NULL ## added
    if (mfill) {
        if (plot) {
            fill <- rep(fill, length.out = n.leg)
            rect2(left = xt, top = yt + ybox/2, dx = xbox, dy = ybox, 
                col = fill, density = density, angle = angle, 
                border = border)
            fillList <- data.frame(left = xt, top = yt + ybox/2, dx = xbox, dy = ybox) ## added
        }
        xt <- xt + dx.fill
    }

Find the very last line and change it to

    invisible(list(rect = list(w = w, h = h, left = left, top = top), 
        text = list(x = xt, y = yt), fillList=fillList)) ## modified

Now call legend via

output <- legend(...) ## replace ... with whatever you want to have as inputs

and the draw triangles using the information returned by legend() like so:

    with(output$fillList[1,], { ## first box
        polygon(c(left, left+dx, left+dx), c(top, top, top-dy), col=myColour, border=NA)
    })

Result