missing factor levels in a lattice barchart panel cause unexpected failure
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