I wondered if there is a way by which scatterplot point colours can be allocated to specific panels using the custom panel function capabilities of base R's pairs()
plot? There are plenty of examples of colouring by factor within each panel, but I can't find anything whereby a single colour can be allocated to all points in a given panel, and a different colour to the points in another. There is probably something clever which can be done by accessing the indices of the paired combinations of columns, and getting pairs()
to pass that to a custom panel function, but I cannot figure it out.
This is a terrible hack, but you can do it by searching up the call stack for the row/column indices of the current panel ...
pp <- function(x, y) {
## extract panel indices
i <- parent.frame(2)$i
j <- parent.frame(2)$j
col <- if (i==1 && j == 3) "red" else "black"
points(x, y, col = col)
}
pairs(mtcars[,1:5], panel = pp, gap = 0)
What is parent.frame(2)
doing? Here is the call stack when pp
is called (gotten by saying debug(pp)
, then issuing where
from within the debugging environment):
where 1: upper.panel(...)
where 2: localUpperPanel(as.vector(x[, j]), as.vector(x[, i]), ...)
where 3: pairs.default(mtcars[, 1:5], panel = pp, gap = 0)
where 4: pairs(mtcars[, 1:5], panel = pp, gap = 0)
parent.frame(2)
means "retrieve the environment two steps up the call stack", i.e. the environment of pairs.default
. pairs.default
runs a for
loop over the row (i
) and column (j
) indices, and so we can retrieve the current values of those indices from that environment. I figured this out by putting a browser()
statement inside my panel
function, then inspecting the contents of the environment one level up (ls(parent.frame(1))
), not finding anything that looked like row/column indices, and trying ls(parent.frame(2))
...