[R] Auto.key colors maintained when subsetting

David Afshartous dafshartous at med.miami.edu
Wed Jul 9 21:13:53 CEST 2008




On 7/9/08 1:07 PM, "Deepayan Sarkar" <deepayan.sarkar at gmail.com> wrote:

> On 7/9/08, David Afshartous <dafshartous at med.miami.edu> wrote:
>> 
>> 
>>  All,
>> 
>>  I'm plotting points and lines for various groups.
>>  I'd like subsequent plots done on subsets to maintain the color assignments
>>  from the original plot.  This works fine, but the key for the subset doesn't
>>  maintain the correspondence.  One solution is to reprint the entire key, but
>>  this is undesirable since then the key has more elements than the groups in
>>  the plot.  Reproducible example below.
> 
> Well, the ideal solution would have been for auto.key to magically
> omit the levels of 'groups' that are omitted by the application of
> 'subset', but there is not enough information available to it for this
> to happen. One option is to
> 
> 1. subset the data beforehand, and drop unsed levels with Group[drop=TRUE]
> 

This will work, but unfortunately the color correspondence across plots will
be lost.  Leading to a preference for your second suggestion:


> 2. supply colors, etc. explicitly through 'par.settings'.
> 

The code below works, but when extended to include error bars (panel.ci, and
prepanel.ci), it works for the full data but not the subset.

## full data w/ colors supplied, this works:
xyplot(Y ~ Hour,
        data = dat, pch = 16,
        groups=Group, col=c('red', 'black', 'green', 'blue'),
        type="b",
        auto.key = list(space = "top",  text = levels(Group),
         points = FALSE, lines = TRUE, columns=4),
        par.settings = list(superpose.line = list(lty = c(1,2,3,4),
         col=c('red', 'black', 'green', 'blue')
) ) )


## subset of data; this works:
dev.new() xyplot(Y ~ Hour,
        data = dat, pch = 16,
        subset = (Group != "A"),
        groups=Group, col=c('red', 'black', 'green', 'blue'),
         lty = c(1,2,3,4),
        type="b",
        auto.key = list(space = "top",  text = levels(Group)[2:4],
         points = FALSE, lines = TRUE, columns=3),
        par.settings = list(superpose.line = list(lty = c(2,3,4),
         col=c('black', 'green', 'blue')
) ) )


## full data w/ error bars, this works:
xyplot(Y ~ Hour,
        data = dat, pch = 16,
        groups=Group, col=c('red', 'black', 'green', 'blue'),
         lty = c(1,2,3,4),
        ly = dat$lower.bound ,
        uy = dat$upper.bound ,
        prepanel = prepanel.ci,
        panel = panel.superpose,
        panel.groups = panel.ci,
        type="b",
        auto.key = list(space = "top",  text = levels(Group),
         points = FALSE, lines = TRUE, columns=4),
        par.settings = list(superpose.line = list(lty = c(1,2,3,4),
         col=c('red','black', 'green', 'blue')
) ) )


## subset of data w/ error bars produces error message: Error using packet
## 1, Invalid Line Type:

xyplot(Y ~ Hour,
        data = dat, pch = 16,
        subset = (Group != "A"),
        groups=Group, col=c('red', 'black', 'green', 'blue'),
         lty = c(1,2,3,4),
        ly = dat$lower.bound ,
        uy = dat$upper.bound ,
        prepanel = prepanel.ci,
        panel = panel.superpose,
        panel.groups = panel.ci,
        type="b",
        auto.key = list(space = "top",  text = levels(Group)[2:4],
         points = FALSE, lines = TRUE, columns=3),
        par.settings = list(superpose.line = list(lty = c(2,3,4),
         col=c('black', 'green', 'blue')
) ) )

> The other option is to construct your own key (i.e., use the 'key'
> argument, not 'auto.key', to specify the legend).

Below is an attempt to use key; although the plot is correct, in the key the
color is applied to the text instead of the line and the line type isn't
drawn:

xyplot(Y ~ Hour,
        data = dat, pch = 16,
        subset = (Group != "A"),
        groups=Group, col=c('red', 'black', 'green', 'blue'),
        type="b",
        key = simpleKey(text = levels(Group)[2:4], lty = c(2,3,4),
             space = "top", columns = 3, points = FALSE, lines = TRUE,
             col = c('black', 'green', 'blue'))
        par.settings = list(superpose.line = list(lty = c(1,2,3,4),
         col=c('red', 'black', 'green', 'blue')
) ) )


#############################
Data and necessary functions:
set.seed(101)
Y = c(rnorm(4,0), rnorm(4,2), rnorm(4,6), rnorm(4,8))
dat = data.frame(
    Y , lower.bound = Y - .5, upper.bound = Y + .5,
    Group = factor(c(rep("A", 4), rep("B", 4), rep("C", 4), rep("D", 4))),
    
Hour = rep(c(1:4), 4)
)
prepanel.ci <- function(x, y, ly, uy, subscripts, ...) {
    x <- as.numeric(x)
    ly <- as.numeric(ly[subscripts])
    uy <- as.numeric(uy[subscripts])
    list(ylim = range(y, uy, ly, finite = TRUE)) }
panel.ci <- function(x, y, ly, uy, subscripts, pch = 16, ...) {
    x <- as.numeric(x)
    y <- as.numeric(y)
    ly <- as.numeric(ly[subscripts])
    uy <- as.numeric(uy[subscripts])
    panel.arrows(x, ly, x, uy, col = "black",
                 length = 0.25, unit = "native",
                 angle = 90, code = 3)
    panel.xyplot(x, y, pch = 16, ...)}








> It should be simple
> to write a function that constructs a suitable 'key' argument given
> the levels that are to be omitted/retained.
> 
> -Deepayan



More information about the R-help mailing list