Bryan Hanson
Bryan Hanson

Reputation: 6223

Custom Lattice Function: Getting Colors Correct Across Panels

I'm trying to control the color of data points in a custom Lattice function. The idea is the response may be a function of one or two factors. The coloring of the data points should be determined by fac1. Here is the function:

compareCats <-
function(formula = NULL, data = NULL, cols = NULL, ...) {

    TwoFac <- FALSE
    res <- as.character(formula[[2]])
    if (length(formula[[3]]) == 1) {
        fac1 <- as.character(formula[[3]])
        }
    if (length(formula[[3]]) == 3) {
        fac2 <- as.character(formula[[3]][3])
        fac1 <- as.character(formula[[3]][2])
        TwoFac <- TRUE
        }

    args <- as.list(match.call(expand.dots = FALSE)[-1]) # used a bit later

    if (TwoFac) keep <- c(res, fac1, fac2) # Reduce the df and clean it of NAs
    if (!TwoFac) keep <- c(res, fac1)
    data <- data[, keep]
    data <- na.omit(data)

    # cols2 is used for the data points according to levels in fac1
    if (!TwoFac) cols2 <- cols[data[,fac1]] # works fine
    if (TwoFac) {
        # In this case, the points and panels are drawn in an order I don't understand
        cols2 <- rep(NA_character_, nrow(data))
        for (i in 1:nlevels(data[,fac1])) { # make the colors correspond to the original order
            tmp <- which(data[,fac1] == levels(data[,fac1])[i])
            cols2[tmp] <- cols[i]
            }
        }
    data$cols <- cols2

    p <- lattice::xyplot(as.formula(args$formula), # now the plot
        data = eval(args$data), ...,
        panel = function(x, y, ...) {
            lattice::panel.xyplot(x, y, col = data$cols, ...)
            }
            )
    return(p)   
    }

And here is data and two function calls:

set.seed(13)
mydf <- data.frame(
resp = rnorm(40),
cat1 = sample(LETTERS[1:3], 40, replace = TRUE),
cat2 = sample(letters[1:2], 40, replace = TRUE))
library("lattice")
library("plyr")
# One factor / works fine
p <- compareCats(formula = resp~cat1, data = mydf,
cols = c("red", "orange", "blue"))
print(p)
# Two factors / colors not assigned correctly
p <- compareCats(formula = resp~cat1 | cat2, data = mydf,
cols = c("red", "orange", "blue"))
print(p)

The first produces this diagram: enter image description here and the second this one: enter image description here How do I get the colors in the 2nd example to be red, orange, blue, red, orange, blue, from left to right? I've tried numerous approaches and can get the first panel to behave sometimes but the 2nd panel seems random. Obviously I don't quite see what order Lattice uses in the 2 factor case, the docs suggest the interaction is used but that still leaves several possibilities, none of which I have been able to figure out.

Upvotes: 1

Views: 48

Answers (1)

MrFlick
MrFlick

Reputation: 206546

If you want to change colors of points consistently across panels, I suggested you do that via the more standard groups= argument. I would change these two linesin your compareCats function

cols2 <- factor(cols2, levels=cols) # no need to attach to data
p <- lattice::xyplot(as.formula(args$formula), groups=cols2,
    data = eval(args$data), ...,
    par.settings=list(superpose.symbol=list(col=cols))
)

Here we use groups= to assign a points to different groups and we use superpose.symbol to specify which color to assign to each group.

enter image description here

Upvotes: 1

Related Questions