Skip to content

adding error bars to lattice plots

5 messages · Bert Gunter, Mario Aigner-Torres, Deepayan Sarkar

#
?llines, lsegments and the like can be used in the panel functions to draw
any sort of error bar that you can compute from the x,y,... data of the
panel.

-- Bert Gunter
Genentech Non-Clinical Statistics
South San Francisco, CA
 
"The business of the statistician is to catalyze the scientific learning
process."  - George E. P. Box
#
On 10/20/05, Mario Aigner-Torres <mario.aignertorres at gmail.com> wrote:
How are your error bars defined?
6 days later
#
On 10/20/05, Mario Aigner-Torres <mario.aignertorres at gmail.com> wrote:
[...]
[...]

Generally speaking, you need to pass some auxiliary variables to the
panel function. This is easy to do, since all unrecognized arguments
are passed to the panel function anyway. The trick is to figure out
inside the panel function which elements of these variables correspond
to the subset of data in that panel. This is done using the subscripts
argument. So, for example, you can define


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


and then add these to your call, supplying suitable values for lx and
ux (the vectors of lower and upper limits). The one glitch with this
approach is that unlike variables in the formula (and groups, which is
treated specially because of its ubiquity but  otherwise works on
exactly the same principle), lx and ly will not be evaluated in
'data'.  I like to use 'with' to get around this. Here's an example
with the singer data, it should be easy to translate to your example.

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

## show the data frame
singer.ucl

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

-Deepayan