Hi:

Yesterday, I posted a question regarding how to handle different graphical
behavior between two factors in xyplot() [package lattice]. After a public
and private reply from Deepayan Sarkar, the problem has been resolved
nicely, including the addition of a stacked legend for the two factors in
question. The latter requires package latticeExtra.

library(lattice)
library(latticeExtra)

# Test data:
d <- data.frame(time = rep(1:8, each = 6), val = rnorm(48),
                gp1 = factor(rep(1:6, 8)),
                gp2 = factor(rep(rep(c('A', 'B'), each = 3), 8)))

mypch <- 1:6
mycol <- 1:6

# Define individual keys for each of the two factors
# Details on xyplot() help page

mykey1 <- list(title = 'Group 1',
               cex.title = 1.2,
              text = list(levels(d$gp1), cex = 0.8),
              points = list(pch = 1:6, col = 1:6), cex = 0.8)
mykey2 <- list(title = 'Group 2',
               cex.title = 1.2,
              text = list(levels(d$gp2)),
              lines = list(lty = 1, col = c('blue', 'orange')))

# Create a grob by merging the two keys - from latticeExtra (Felix Andrews)
mylegend <-
   mergedTrellisLegendGrob(list(fun = draw.key, args = list(key = mykey1)),
                           list(fun = draw.key, args = list(key = mykey2)),
                           vertical = TRUE)

# Generate the plot:
with(d,
    xyplot(val ~ time,
           pch = mypch, col = mycol,
           lty = 1, col.line = c('blue', 'red'),
           subscripts = TRUE,
           panel = function(x, y, ..., groups) {
               panel.superpose(x, y, ..., groups = gp1, panel =
panel.points)
               panel.superpose(x, y, ..., groups = gp2, panel = panel.loess)
           },
           par.settings = list(layout.widths = list(key.right = 1.6)),
           legend = list(right = list(fun = mylegend))))

The panel function uses panel.superpose to separate the task of plotting
points according to the levels of gp1 from the task of producing loess fits
to the groups in gp2. In particular, panel.loess is not 'group aware', so
the panel.superpose code is necessary to plot loess smooths by group in this
context. Note the subscripts = TRUE argument *outside* of the panel function
so that the panel function can operate on the groups. The legend statement
uses mylegend as the argument to fun, where fun can either be a grob (which
mylegend happens to be here) or a function; in the latter case, the function
needs to be followed by args = list(...), where ... is a placeholder for the
assigned values of the function arguments. [See the call to
mergedTrellisLegendGrob(), for example.] Finally, par.settings is used in
this context to provide extra horizontal space on the right to comfortably
contain the legend contents.

Thanks to Deepayan for his lucid and informative replies. I hope this will
be of use to others.

Regards,
Dennis

	[[alternative HTML version deleted]]

