[R] lattice: aligning independent graphs

Deepayan Sarkar deepayan.sarkar at gmail.com
Mon May 28 00:09:43 CEST 2007


On 5/26/07, Zack Weinberg <zack at cogsci.ucsd.edu> wrote:
> I find myself wanting to plot three graphs side by side 'as if' they
> were panels -- that is, with the same y-axis limits, no space between
> the graphs, and precise vertical alignment of the plot areas. However,
> I don't want strip titles; I want each graph to have its own x-axis
> label, on the bottom of the plot.
>
> The best way I have so far found to do this is to fake up a data frame
> that allows me to use actual panels, turn off the strip, and insert a
> whole bunch of white space in the x-axis label so it looks like there
> are three separate labels.  Like this:
>
> xyplot(x ~ thing | panel,
>        data=wrong.all,
>        ylab=list(label='% incorrect responses', cex=0.7),
>        xlab=list(label=paste('Trial number                                 ',
>                              'Subject number                              ',
>                              'Experimental condition'), cex=0.7),
>        ylim=c(0,top), col='black', pch=3, strip=F,
>        scales=list(
>          x=list(alternating=c(1,0), tck=c(1,0), cex=0.5, rot=90,
>            relation='free',
>            at=list(
>              seq(0,33,by=5),
>              seq(0,maxsub, by=5),
>              seq(1,length(levels(wrongconds)))),
>            labels=list(seq(0,33,by=5), seq(0,maxsub, by=5),
>              levels(wrongconds))),
>          y=list(at=seq(0,top,by=10), alternating=c(1,0),
>            tck=c(1,1),
>            cex=0.5)),
>        type=list(c('p','smooth'), 'h', 'h'),
>        panel=function(..., type=list("p")) {
>          panel.grid(h=-1, v=0)
>          panel.xyplot(..., type=type[[panel.number()]])
>        })
>
> But surely there is a better way?

Better in what sense? You are trying to use lattice to do something
that lattice isn't designed to do, so there is no solution that is
"clean" in a philosophical sense. Ideally, you want something like
grid, that allows you to control the layout in as much detail as you
want (you can still use panel.xyplot, panel.grid, etc. as "panel
functions" once you set up everything else). On the other hand,
lattice gets you very close, and the only improvement I can think of
is some sort of automated scheme to align the x labels to the
respective columns. Here's one approach to do that (taking advantage
of the fact that xlab can be an arbitrary "grob"):


library(grid)

myXlabGrob <-
   function(...) ## ...is lab1, lab2, etc
{
   ## you can add arguments to textGrob for more control
   ## in the next line
   labs <- lapply(list(...), textGrob)
   nlabs <- length(labs)
   lab.heights <-
       lapply(labs,
              function(lab) unit(1, "grobheight", data = list(lab)))
   lab.layout <-
       grid.layout(ncol = nlabs, nrow = 1,
                   heights = do.call(max, lab.heights),
                   widths = unit(1, "null"),
                   respect = TRUE)
   lab.gf <- frameGrob(layout = lab.layout)
   for (i in seq_len(nlabs))
   {
       lab.gf <- placeGrob(lab.gf, labs[[i]], row = 1, col = i)
   }
   lab.gf
}


xyplot(1:9 ~ 1:9 | gl(3, 1, 9),
       layout = c(3, 1),
       xlab =
       myXlabGrob('Trial number',
                  'Subject number',
                  'Experimental condition'),
       strip = FALSE)

-Deepayan



More information about the R-help mailing list