[R] Auto.key colors maintained when subsetting

David Afshartous dafshartous at med.miami.edu
Thu Jul 10 00:12:09 CEST 2008


I've determined that the problem with getting the subsetting to work with
the error bars was related to not dropping the unused levels of the Grouping
factor.  The simplest solution was to follow a combination of Deepayan's
suggestions 1 and 2 below, i.e., supply one's own colors and subset
beforehand:

## full data w/ error bars, this works:
xyplot(Y ~ Hour,
        data = dat, pch = 16,
        groups=Group, col=c('red', 'black', 'green', 'blue'),
        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(dat$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')
) ) )

dev.new()
junk = dat[dat$Group != "A", ]
junk$Group = junk$Group[1:length(junk$Group), drop = T]

## this works below, but one has to be careful w/ the line
## types and colors in par.settings to make sure they match
## previous figure

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





On 7/9/08 3:13 PM, "David Afshartous" <dafshartous at med.miami.edu> wrote:

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