[R] adding error bars to lattice plots

Deepayan Sarkar deepayan.sarkar at gmail.com
Thu Oct 12 21:29:16 CEST 2006


On 10/12/06, Daniel E. Bunker <deb37 at columbia.edu> wrote:
> Dear R users,
>
> About a year ago Deepayan offered a suggestion to incorporate error bars
> into a dotplot using the singer data as an example
> <<http://finzi.psych.upenn.edu/R/Rhelp02a/archive/63875.html>>.
>
> When I try to utilize this code with a grouping variable, I get an error
> stating that the subscripts argument is missing.  I have tried to insert
> them in various ways, but cannot figure out where they should go.
>
> Deepayan's original code follows, with additions from me for factor,
> grouping and by variables.
>
> (Note that I could use xYplot (Dotplot), but I need my response variable
> on the vertical axis.)
>
> Any suggestions would be greatly appreciated.
>
> Thanks, Dan
>
> prepanel.ci <- function(x, y, lx, ux, subscripts, ...) {
>         x <- as.numeric(x)
>         lx <- as.numeric(lx[subscripts])
>          ux <- as.numeric(ux[subscripts])
>          list(xlim = range(x, ux, lx, finite = TRUE))
>      }
>
> panel.ci <- function(x, y, lx, ux, subscripts, pch = 16, ...) {
>          x <- as.numeric(x)
>          y <- as.numeric(y)
>          lx <- as.numeric(lx[subscripts])
>          ux <- as.numeric(ux[subscripts])
>          panel.abline(h = unique(y), col = "grey")
>          panel.arrows(lx, y, ux, y, col = 'black',
>                   length = 0.25, unit = "native",
>                   angle = 90, code = 3)
>          panel.xyplot(x, y, pch = pch, ...)
>      }
>
> singer.split <-
>      with(singer,
>           split(height, voice.part))
>
> singer.ucl <-
>      sapply(singer.split,
>             function(x) {
>                 st <- boxplot.stats(x)
>                 c(st$stats[3], st$conf)
>             })
>
> singer.ucl <- as.data.frame(t(singer.ucl))
> names(singer.ucl) <- c("median", "lower", "upper")
> singer.ucl$voice.part <-
>      factor(rownames(singer.ucl),
>             levels = rownames(singer.ucl))
>
> # add factor, grouping and by variables
> singer.ucl$fac1=c("level1","level1", "level2", "level2")
> singer.ucl$by1=c("two","one")
> singer.ucl$group1=c(rep(letters[1],4),rep(letters[2],4))
>
> ## show the data frame
> singer.ucl
>
> # Deepayan's original example
> with(singer.ucl,
>       xyplot(voice.part ~ median,
>              lx = lower, ux = upper,
>              prepanel = prepanel.ci,
>              panel = panel.ci),
>          horizontal=FALSE)
>
> # with by variable, works fine
> with(singer.ucl,
>       xyplot(voice.part ~ median|by1,
>              lx = lower, ux = upper,
>              prepanel = prepanel.ci,
>              panel = panel.ci))
>
> # with groups, fails for lack of subscripts.
> with(singer.ucl,
>       xyplot(voice.part ~ median, groups=group1,
>              lx = lower, ux = upper,
>              prepanel = prepanel.ci,
>              panel = panel.ci))

Although that does seem to be the eventual error message, this fails
not due to the lack of subscripts, but because 'panel.ci' does not
know how to deal with groups. One solution to this is Sundar's
approach, which is to change the panel function to handle groups.
Another generic solution is to use 'panel.superpose', which _does_
know how to handle groups, and also accepts a custom panel function to
be called for each group. Often (but not always), you can use a panel
function designed for a non-groups aware display for this. In this
case, the following gives results similar to Sundar's code:

with(singer.ucl,
     xyplot(voice.part ~ median, groups=group1,
            lx = lower, ux = upper,
            prepanel = prepanel.ci,
            panel = panel.superpose,
            panel.groups = panel.ci,
            pch = 16))

Note the need for an explicit pch=16, since the default in panel.ci is
overridden by panel.groups.

> # what I need, ultimately, is something like this, with error bars:
>
> with(singer.ucl,
>       dotplot(median~fac1|by1, groups=group1))

If you have more than one interval (from different groups) for any
level of your categorical variable - which seems to be the case in
this example - you will encounter a problem. The problem is this: the
grey reference lines are drawn once for every group, and will draw
over intervals drawn by calls corresponding to earlier levels. This
can be easily fixed by moving that part of the code from
'panel.groups' to 'panel', I'll leave that as an exercise.

-Deepayan



More information about the R-help mailing list