# [R] conditioned xyplot, many y variables

Deepayan Sarkar deepayan.sarkar at gmail.com
Sun Feb 7 20:10:37 CET 2010

```On Sun, Feb 7, 2010 at 9:32 AM, Jacob Wegelin <jacobwegelin at fastmail.fm> wrote:
>
> The example below creates parallel time-series plots of three different y
> variables conditioned by a dichotomous factor. In the graphical layout,
>
>        •       Each y variable inhabits its own row and is plotted on its
> own distinct scale.
>
>        •       Each level of the factor has its own column, but within each
> row the scale is held constant across columns.
>
>        •       The panels fit tightly (as they do in lattice) without
> superfluous whitespace or ticks.
>
> Currently I know of no lattice solution to this problem, only a traditional
> graphics solution. Can one solve this problem elegantly using lattice?

Yes, for some definition of "elegantly". See below.

> The difficulty is to lock the levels of the factor (the columns) into the
> same scale for each y variable (for each row), while allowing the scales to
> differ between the y variables (between the rows).

This is not generally possible, as this makes sense only when rows and
columns correspond to conditioning variables, which is not always
true. (It is true for two conditioning variables with the default
layout, but lattice does not treat that case specially.)

(1) modify the limits to get "same" limits across rows,
(2) remove the labels for the second column, and
(3) remove the space allocated for those labels
to get what you want:

## assign the trellis object to a variable for further manipulation

fplot <-
xyplot ( ppp + QQQ + z ~ TIME | Species
, group=ID
, data=JUNK
, ylab=c("ppp (mg/L)", "QQQ (pg/L)", "z (mIU/mL)")
, xlab=c("Dog", "feline")
, type="o"
, strip= FALSE
, outer=TRUE
, layout=c(2,3)
, scales=list(
ppp=list( alternating=3)
, y=list(
relation="free"
, alternating=3
, rot=0
, log=T
)
)
)

## massage the limits (stored in fplot\$y.limits) so that rows have the
## same limits.  The limits are stored as a linear list, and it is
## useful to make it an array first.

str(fplot\$y.limits)

dim(fplot\$y.limits) <- dim(fplot)

for (i in seq_len(ncol(fplot\$y.limits)))
{
rng <- range(unlist(fplot\$y.limits[,i]))
for (j in seq_len(nrow(fplot\$y.limits)))
fplot\$y.limits[j, i][] <- rng
}

str(fplot\$y.limits)

## Next, drop the y-axis labels for the second column, and zap the
## space allocated for them.

update(fplot,
scales = list(y =
list(at = rep(list(NA, numeric(0)), 3))),
par.settings = list(layout.widths = list(axis.panel = c(1, 0))))

(Maybe I should wrap this up in a helper function.)

-Deepayan

>
> Details:
>
> #       Toy data:
>
> N<-15
> TIME <- (1:N)/N
> ppp <- TIME^2
> QQQ <- exp(TIME)
> z <- ppp / QQQ
> JUNK<-data.frame( ppp=ppp, QQQ=QQQ, z=z, TIME=TIME)
> JUNK\$ID<-1
> jank<-JUNK
> jank\$ID<-2
> jank\$ppp<-jank\$ppp / 2
> jank\$QQQ<-jank\$QQQ / 2
> jank\$z<-jank\$ppp/jank\$QQQ
> JUNK<-rbind(JUNK, jank)
> jank<-JUNK
> jank\$ppp<-(jank\$ppp) ^(1/4)
> jank\$QQQ<-(jank\$QQQ) / 100000
> jank\$z <- jank\$ppp / jank\$QQQ
> JUNK\$Species<-"Dog"
> jank\$Species<-"feline"
> JUNK<-rbind(JUNK, jank)
> JUNK\$Species<-factor(JUNK\$Species)
> JUNK\$ID<-factor(JUNK\$ID)
> summary(JUNK)

```