Looking for a cleaner way of making a floating bar chart that shows time and duration of events split apart by factor (see Cleveland's Elements of Graphing Data, Fig. 2.4). The following lattice code gets the job done, but is clunky. Is there a more direct way of doing this?
library(lattice)
set.seed(1)
x = sort(unique(sample(1:1000, 40)))
z <- data.frame(x = x, state = c("on", "off"))
z2 <- data.frame(on = z[z$state=="on", ]$x,
off = z[z$state=="off", ]$x)
# needed for panel.rect
z2$mp <- with(z2, (on+off)/2) # x-midpoint
z2$w <- with(z2, off-on) # x-width
z2$lab <- rep(factor(c("a", "b", "c", "d")), 5)
xyplot(lab ~ on + off + mp + w, z2,
panel = function(x, y, subscripts, groups, ...){
panel.rect(y = y[subscripts],
x = x[subscripts[groups=="mp"]],
width = x[subscripts[groups=="w"]],
height = 0.5, ...)
})
Specifically, the formula lab ~ on + off + mp + w
is needed to provide the panel function with the necessary points, while the on + off
variables are needed to automatically size the plot. I'd like this better if the panel function did not need to know specific variable names.
Bonus points if the cleaner solution works with a conditioning variable, ideally in the form: lab ~ on + off | cvar
.