Dear R users, About a year ago Deepayan offered a suggestion to incorporate error bars into a dotplot using the singer data as an example <<http://finzi.psych.upenn.edu/R/Rhelp02a/archive/63875.html>>. When I try to utilize this code with a grouping variable, I get an error stating that the subscripts argument is missing. I have tried to insert them in various ways, but cannot figure out where they should go. Deepayan's original code follows, with additions from me for factor, grouping and by variables. (Note that I could use xYplot (Dotplot), but I need my response variable on the vertical axis.) Any suggestions would be greatly appreciated. Thanks, Dan prepanel.ci <- function(x, y, lx, ux, subscripts, ...) { x <- as.numeric(x) lx <- as.numeric(lx[subscripts]) ux <- as.numeric(ux[subscripts]) list(xlim = range(x, ux, lx, finite = TRUE)) } panel.ci <- function(x, y, lx, ux, subscripts, pch = 16, ...) { x <- as.numeric(x) y <- as.numeric(y) lx <- as.numeric(lx[subscripts]) ux <- as.numeric(ux[subscripts]) panel.abline(h = unique(y), col = "grey") panel.arrows(lx, y, ux, y, col = 'black', length = 0.25, unit = "native", angle = 90, code = 3) panel.xyplot(x, y, pch = pch, ...) } singer.split <- with(singer, split(height, voice.part)) singer.ucl <- sapply(singer.split, function(x) { st <- boxplot.stats(x) c(st$stats[3], st$conf) }) singer.ucl <- as.data.frame(t(singer.ucl)) names(singer.ucl) <- c("median", "lower", "upper") singer.ucl$voice.part <- factor(rownames(singer.ucl), levels = rownames(singer.ucl)) # add factor, grouping and by variables singer.ucl$fac1=c("level1","level1", "level2", "level2") singer.ucl$by1=c("two","one") singer.ucl$group1=c(rep(letters[1],4),rep(letters[2],4)) ## show the data frame singer.ucl # Deepayan's original example with(singer.ucl, xyplot(voice.part ~ median, lx = lower, ux = upper, prepanel = prepanel.ci, panel = panel.ci), horizontal=FALSE) # with by variable, works fine with(singer.ucl, xyplot(voice.part ~ median|by1, lx = lower, ux = upper, prepanel = prepanel.ci, panel = panel.ci)) # with groups, fails for lack of subscripts. with(singer.ucl, xyplot(voice.part ~ median, groups=group1, lx = lower, ux = upper, prepanel = prepanel.ci, panel = panel.ci)) # what I need, ultimately, is something like this, with error bars: with(singer.ucl, dotplot(median~fac1|by1, groups=group1))
Daniel E. Bunker said the following on 10/12/2006 11:48 AM:> Dear R users, > > About a year ago Deepayan offered a suggestion to incorporate error bars > into a dotplot using the singer data as an example > <<http://finzi.psych.upenn.edu/R/Rhelp02a/archive/63875.html>>. > > When I try to utilize this code with a grouping variable, I get an error > stating that the subscripts argument is missing. I have tried to insert > them in various ways, but cannot figure out where they should go. > > Deepayan's original code follows, with additions from me for factor, > grouping and by variables. > > (Note that I could use xYplot (Dotplot), but I need my response variable > on the vertical axis.) > > Any suggestions would be greatly appreciated. > > Thanks, Dan > > prepanel.ci <- function(x, y, lx, ux, subscripts, ...) { > x <- as.numeric(x) > lx <- as.numeric(lx[subscripts]) > ux <- as.numeric(ux[subscripts]) > list(xlim = range(x, ux, lx, finite = TRUE)) > } > > panel.ci <- function(x, y, lx, ux, subscripts, pch = 16, ...) { > x <- as.numeric(x) > y <- as.numeric(y) > lx <- as.numeric(lx[subscripts]) > ux <- as.numeric(ux[subscripts]) > panel.abline(h = unique(y), col = "grey") > panel.arrows(lx, y, ux, y, col = 'black', > length = 0.25, unit = "native", > angle = 90, code = 3) > panel.xyplot(x, y, pch = pch, ...) > } > > singer.split <- > with(singer, > split(height, voice.part)) > > singer.ucl <- > sapply(singer.split, > function(x) { > st <- boxplot.stats(x) > c(st$stats[3], st$conf) > }) > > singer.ucl <- as.data.frame(t(singer.ucl)) > names(singer.ucl) <- c("median", "lower", "upper") > singer.ucl$voice.part <- > factor(rownames(singer.ucl), > levels = rownames(singer.ucl)) > > # add factor, grouping and by variables > singer.ucl$fac1=c("level1","level1", "level2", "level2") > singer.ucl$by1=c("two","one") > singer.ucl$group1=c(rep(letters[1],4),rep(letters[2],4)) > > ## show the data frame > singer.ucl > > # Deepayan's original example > with(singer.ucl, > xyplot(voice.part ~ median, > lx = lower, ux = upper, > prepanel = prepanel.ci, > panel = panel.ci), > horizontal=FALSE) > > # with by variable, works fine > with(singer.ucl, > xyplot(voice.part ~ median|by1, > lx = lower, ux = upper, > prepanel = prepanel.ci, > panel = panel.ci)) > > # with groups, fails for lack of subscripts. > with(singer.ucl, > xyplot(voice.part ~ median, groups=group1, > lx = lower, ux = upper, > prepanel = prepanel.ci, > panel = panel.ci)) > > > # what I need, ultimately, is something like this, with error bars: > > with(singer.ucl, > dotplot(median~fac1|by1, groups=group1)) > > ______________________________________________ > R-help at stat.math.ethz.ch mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code.Hi, Daniel, Try this panel function: panel.ci <- function(x, y, lx, ux, subscripts, groups = NULL, pch = 16, ...) { x <- as.numeric(x) y <- as.numeric(y) lx <- as.numeric(lx[subscripts]) ux <- as.numeric(ux[subscripts]) par <- if(is.null(groups))"plot.symbol" else "superpose.symbol" sym <- trellis.par.get(par) col <- sym$col groups <- if(!is.null(groups)) { groups[subscripts] } else { rep(1, along = x) } ug <- unique(groups) for(i in seq(along = ug)) { subg <- groups == ug[i] y.g <- y[subg] x.g <- x[subg] lx.g <- lx[subg] ux.g <- ux[subg] panel.abline(h = unique(y.g), col = "grey") panel.arrows(lx.g, y.g, ux.g, y.g, col = 'black', length = 0.25, unit = "native", angle = 90, code = 3) panel.xyplot(x.g, y.g, pch = pch, col = col[i], ...) } }
On 10/12/06, Daniel E. Bunker <deb37 at columbia.edu> wrote:> Dear R users, > > About a year ago Deepayan offered a suggestion to incorporate error bars > into a dotplot using the singer data as an example > <<http://finzi.psych.upenn.edu/R/Rhelp02a/archive/63875.html>>. > > When I try to utilize this code with a grouping variable, I get an error > stating that the subscripts argument is missing. I have tried to insert > them in various ways, but cannot figure out where they should go. > > Deepayan's original code follows, with additions from me for factor, > grouping and by variables. > > (Note that I could use xYplot (Dotplot), but I need my response variable > on the vertical axis.) > > Any suggestions would be greatly appreciated. > > Thanks, Dan > > prepanel.ci <- function(x, y, lx, ux, subscripts, ...) { > x <- as.numeric(x) > lx <- as.numeric(lx[subscripts]) > ux <- as.numeric(ux[subscripts]) > list(xlim = range(x, ux, lx, finite = TRUE)) > } > > panel.ci <- function(x, y, lx, ux, subscripts, pch = 16, ...) { > x <- as.numeric(x) > y <- as.numeric(y) > lx <- as.numeric(lx[subscripts]) > ux <- as.numeric(ux[subscripts]) > panel.abline(h = unique(y), col = "grey") > panel.arrows(lx, y, ux, y, col = 'black', > length = 0.25, unit = "native", > angle = 90, code = 3) > panel.xyplot(x, y, pch = pch, ...) > } > > singer.split <- > with(singer, > split(height, voice.part)) > > singer.ucl <- > sapply(singer.split, > function(x) { > st <- boxplot.stats(x) > c(st$stats[3], st$conf) > }) > > singer.ucl <- as.data.frame(t(singer.ucl)) > names(singer.ucl) <- c("median", "lower", "upper") > singer.ucl$voice.part <- > factor(rownames(singer.ucl), > levels = rownames(singer.ucl)) > > # add factor, grouping and by variables > singer.ucl$fac1=c("level1","level1", "level2", "level2") > singer.ucl$by1=c("two","one") > singer.ucl$group1=c(rep(letters[1],4),rep(letters[2],4)) > > ## show the data frame > singer.ucl > > # Deepayan's original example > with(singer.ucl, > xyplot(voice.part ~ median, > lx = lower, ux = upper, > prepanel = prepanel.ci, > panel = panel.ci), > horizontal=FALSE) > > # with by variable, works fine > with(singer.ucl, > xyplot(voice.part ~ median|by1, > lx = lower, ux = upper, > prepanel = prepanel.ci, > panel = panel.ci)) > > # with groups, fails for lack of subscripts. > with(singer.ucl, > xyplot(voice.part ~ median, groups=group1, > lx = lower, ux = upper, > prepanel = prepanel.ci, > panel = panel.ci))Although that does seem to be the eventual error message, this fails not due to the lack of subscripts, but because 'panel.ci' does not know how to deal with groups. One solution to this is Sundar's approach, which is to change the panel function to handle groups. Another generic solution is to use 'panel.superpose', which _does_ know how to handle groups, and also accepts a custom panel function to be called for each group. Often (but not always), you can use a panel function designed for a non-groups aware display for this. In this case, the following gives results similar to Sundar's code: with(singer.ucl, xyplot(voice.part ~ median, groups=group1, lx = lower, ux = upper, prepanel = prepanel.ci, panel = panel.superpose, panel.groups = panel.ci, pch = 16)) Note the need for an explicit pch=16, since the default in panel.ci is overridden by panel.groups.> # what I need, ultimately, is something like this, with error bars: > > with(singer.ucl, > dotplot(median~fac1|by1, groups=group1))If you have more than one interval (from different groups) for any level of your categorical variable - which seems to be the case in this example - you will encounter a problem. The problem is this: the grey reference lines are drawn once for every group, and will draw over intervals drawn by calls corresponding to earlier levels. This can be easily fixed by moving that part of the code from 'panel.groups' to 'panel', I'll leave that as an exercise. -Deepayan