[R] missing factor levels in a lattice barchart panel cause unexpected failure

Deepayan Sarkar deepayan.sarkar at gmail.com
Tue Dec 12 23:39:55 CET 2006


On 12/12/06, Alex Brown <alex at transitive.com> wrote:
> I think I've found the problem, and a sort of fix, for this issue.
>
> It appears in the panel.barchart function
>
> each of the clauses in the function has a set of lines roughly like:
>
>              groups <- as.numeric(groupSub(groups, ...))
>              vals <- sort(unique(groups))
>              nvals <- length(vals)
>              col <- rep(col, length = nvals)
>              border <- rep(border, length = nvals)
>              lty <- rep(lty, length = nvals)
>              lwd <- rep(lwd, length = nvals)
>              height <- box.ratio/(1 + nvals * box.ratio)
>              if (reference)
>                  panel.abline(v = origin, col = reference.line$col,
>                    lty = reference.line$lty, lwd = reference.line$lwd)
>              for (i in unique(y)) {
>                  ok <- y == i
>                  nok <- sum(ok, na.rm = TRUE)
>                  panel.rect(x = rep(origin, nok), y = (i + height *
>                    (groups[ok] - (nvals + 1)/2)), col = col[groups[ok]],
>                    border = border[groups[ok]], lty = lty[groups[ok]],
>                    lwd = lwd[groups[ok]], height = rep(height,
>                      nok), width = x[ok] - origin, just = c("left",
>                      "centre"))
>              }
>
> Which sets the parameter lty (and others) to NA in the example below.
>
> > D = data.frame(X=1, Y=factor(letters[2], letters[1:2]))
> > barchart(~ X, D, groups=Y)
>
> This (NA) is because:
>
> groups=[1] b
> Levels: a b
>
> thus the code then does
>
> groups==2
> vals==2
> nvals==1
> ok==TRUE
>
> hence
>
> groups[ok] == 2
>
> but
>
> length(lwd) == 1
>
> thus
>
> lwd[groups[ok]] == lwd[2] == NA
>
> This is due to the mistaken assumption that the numeric component of
> groups must be a subset of the 1:length(groups), when in fact it can
> be a subset of 1:length(levels(groups)).
>
>
> a silly fix:
> ----
>
> replacing
>
>              groups <- as.numeric(groupSub(groups, ...))
>              vals <- sort(unique(groups))
>              nvals <- length(vals)
>
> with
>
>              nvals <- length(levels(groups))
>              groups <- as.numeric(groupSub(groups, ...))
>
> fixes my example, but it clearly short of a full solution.

Why? Seems fine to me. I'll post an update after R 2.4.1 is out next week.

-Deepayan



More information about the R-help mailing list