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?

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).

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)

#       Traditional graphics solution:

par(mfrow=c(3,2),mar=c(0,0,0,0)+0.0,oma=c(4,4,4,1),xpd=FALSE, las=0)

varNamesAndLabels<-data.frame(
        name=c("z", "QQQ", "ppp")
        , label=c("z (mIU/mL)", "QQQ (pg/L)", "ppp (mg/L)")
)
rownames( varNamesAndLabels)<- varNamesAndLabels$name

count_y_variables<-0
for(this_y_name in rownames( varNamesAndLabels) ) {
count_y_variables <- count_y_variables + 1

        countSpecies<-0
        for(thisSpecies in levels(JUNK$Species)) {
                countSpecies<-countSpecies + 1
                TEMPORARY<-JUNK[JUNK$Species==thisSpecies,]
                if(countSpecies==1) {
                        plot(JUNK$TIME, JUNK[[this_y_name]], xlab="", ylab="", 
type="n",xaxt='n', log="y")
                        mtext( varNamesAndLabels[this_y_name,"label"], side=2, 
line=2.5)
                        }
                else
                        plot(JUNK$TIME, JUNK[[this_y_name]] , xlab="", ylab="", type="n",xaxt='n', 
log="y", yaxt="n")
                for( thisID in levels(TEMPORARY$ID)) {
                        lines(TEMPORARY$TIME[TEMPORARY$ID==thisID], 
TEMPORARY[[this_y_name]][TEMPORARY$ID==thisID], type="o")
                        }
                if(count_y_variables == nrow(varNamesAndLabels)) mtext( 
thisSpecies, side=1, line=2.5)
        }
}

library("lattice")

#       The three lattice partial solutions below differ only in the value of 
scales$y$relation.

# scales$y$relation="same" # forces ppp, QQQ, and z to the same scale, which obscures signal,
#       especially for ppp. But at least it enables us to see that the range of 
QQQ
#       differs immensely between Dog and feline.
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="same"
                        , alternating=3
                        , rot=0
                        , log=T
                        )
                )
        )


# scales$y$relation="free" # displays ppp, QQQ, and z on different scales, but it also allows
#       the scales for each variable to differ between Dog and feline.
#       This prevents us from visually comparing the species.
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
                        )
                )
        )


# scales$y$relation="sliced" # shows us that the difference max(z)-min(z) differs greatly between
#       Dog and feline.  But it obscures the fact that
#       QQQ differs wildly between Dog and feline, as we saw when
#       relation="same".
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="sliced"
                        , alternating=3
                        , rot=0
                        , log=T
                        )
                )
        )

Comments:

The traditional graphics solution requires many lines of custom code.  Also, in traditional graphics I was 
unable to get the "ylab" labels to read parallel to the axis at the same time that the tick labels 
read perpendicular to the axis. The lattice package achieves this with "rot=0". In traditional 
graphics, "las" apparently governs the mtext (outer label) as well as the axis tick labels.

Thanks for any insights

Jacob A. Wegelin
Assistant Professor
Department of Biostatistics
Virginia Commonwealth University
730 East Broad Street Room 3006
P. O. Box 980032
Richmond VA 23298-0032
U.S.A.
______________________________________________
R-help@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.

Reply via email to