Rob Hall
Rob Hall

Reputation: 1418

R: legend boxes with more than one colour

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

Upvotes: 0

Views: 1537

Answers (2)

Rob Hall
Rob Hall

Reputation: 1418

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

Upvotes: 0

Pierre Lapointe
Pierre Lapointe

Reputation: 16277

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

Upvotes: 1

Related Questions