[R] How to properly shade the background panels of an xyplot?

Deepayan Sarkar deepayan.sarkar at gmail.com
Fri May 8 01:52:49 CEST 2009


On Thu, May 7, 2009 at 2:50 PM, Daniel Kornhauser <dkor at northwestern.edu> wrote:
> Hi:
>
> Here is simplified example of what I am having trouble with:
> I want to set the gray shade of the background of each panel of a
> xyplot with its mean.
> My aim is to be able to compare at a glance which panel has the highest mean.
> But, in order to achieve this I have to normalize the means between 0 and 1.
> The normalization is necessary to stay within the valid range for the
> gray() command.
> I can’t figure out how to do it :-(
>
> Here is an example where I use max(Oats$yield) (the all around maximum
> value) to normalize.
> Note that what I am looking for is an expression what would mean
> something like this as max(<mean of every panel>)
>
> # Start Example, just copy and paste
> data(Oats, package = "MEMSS")
> tp1.oats <- xyplot(yield ~ nitro | Variety + Block,
>                      data = Oats,
>                      panel = function(x, y, subscripts, ...) {
>                                # How to normalize my heatmap metric with
>                                # the value of the panel that has maximum average ?
>                                # metric = eval(mean(y)/ max(<mean-of-each-panel>)))))
>                                metric = eval(mean(y)/max(Oats$yield))
>                                panel.fill(col = gray(metric))
>                                panel.lines(x,y)
>                          }
>                        )
> print(tp1.oats)
> # End Example
>
> Does anybody have any suggestion how I can get max(<mean-of-each-panel>) ?

The simple answer is to use tapply():

> with(Oats, tapply(yield, list(Variety, Block), mean))
                 I     II    III    IV     V     VI
Golden Rain 133.25 113.25  86.75 108.0 95.50  90.25
Marvellous  129.75 121.25 118.50  95.0 85.25 109.00
Victory     143.00  87.25  82.50  91.5 92.00  89.50

So,

xyplot(yield ~ nitro | Variety + Block,
       data = Oats,
       max.mean = max(with(Oats, tapply(yield, list(Variety, Block), mean))),
       panel = function(x, y, subscripts, max.mean, ...) {
           metric = mean(y)/max.mean
           panel.fill(col = gray(metric))
           panel.lines(x,y)
       })


For the general problem of sharing/aggregating per-panel information,
you can use the prepanel function, which is guaranteed to run once for
every panel (or rather every packet, to be more precise) with the same
arguments as the panel function. This example takes advantage of the
persistence of environments:

xyplot(yield ~ nitro | Variety + Block,
       data = Oats,
       aux.env = new.env(parent = emptyenv()),
       prepanel = function(x, y, aux.env, ...) {
           aux.env$max.mean.y <- max(aux.env$max.mean.y, mean(y))
           list()
       },
       panel = function(x, y, subscripts, aux.env, ...) {
           metric = mean(y) / aux.env$max.mean.y
           panel.fill(col = gray(metric))
           panel.lines(x,y)
       })

-Deepayan



More information about the R-help mailing list