Hi all, I'm trying to plot error bars in a lattice plot generated with xyplot. Deepayan Sarkar has provided a very useful solution for simple circumstances (https://stat.ethz.ch/pipermail/r-help/2005-October/081571.html), yet I am having trouble getting it to work when the "groups" setting is enabled in xyplot (i.e. multiple lines). To illustrate this, consider the singer data generated by the above linked solution previously submitted: ##################### library(lattice) 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)) #now let's split up the voice.part factor into two factors, singer.ucl$voice=factor(rep(c(1,2),4)) singer.ucl$range=factor(rep(c("Bass","Tenor","Alto","Soprano"),each=2)) #here's Deepayan's previous solution, slightly modified to depict # the dependent variable (median) and the error bars on the y-axis # and the independent variable (voice.part) on the x-axis 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 = pch, ...) } #this graph works xyplot(median ~ voice.part, data=singer.ucl, ly = singer.ucl$lower, uy = singer.ucl$upper, prepanel = prepanel.ci, panel = panel.ci, type="b" ) #this one does not (it will plot, but will not seperate the groups) xyplot(median ~ voice, groups=range, data=singer.ucl, ly = singer.ucl$lower, uy = singer.ucl$upper, prepanel = prepanel.ci, panel = panel.ci, type="b" ) #################################### Any suggestions? -- Mike Lawrence Mike.Lawrence at Dal.Ca "The road to Wisdom? Well, it's plain and simple to express: Err and err and err again, but less and less and less." - Piet Hein
On 6/5/06, Mike Lawrence <Mike.Lawrence at dal.ca> wrote:> Hi all, > > I'm trying to plot error bars in a lattice plot generated with xyplot. Deepayan > Sarkar has provided a very useful solution for simple circumstances > (https://stat.ethz.ch/pipermail/r-help/2005-October/081571.html), yet I am > having trouble getting it to work when the "groups" setting is enabled in > xyplot (i.e. multiple lines). To illustrate this, consider the singer data > generated by the above linked solution previously submitted: > > ##################### > library(lattice) > 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)) > > #now let's split up the voice.part factor into two factors, > singer.ucl$voice=factor(rep(c(1,2),4)) > singer.ucl$range=factor(rep(c("Bass","Tenor","Alto","Soprano"),each=2)) > > #here's Deepayan's previous solution, slightly modified to depict > # the dependent variable (median) and the error bars on the y-axis > # and the independent variable (voice.part) on the x-axis > 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 = pch, ...) > } > > > #this graph works > xyplot(median ~ voice.part, > data=singer.ucl, > ly = singer.ucl$lower, > uy = singer.ucl$upper, > prepanel = prepanel.ci, > panel = panel.ci, > type="b" > ) > > #this one does not (it will plot, but will not seperate the groups) > xyplot(median ~ voice, > groups=range, > data=singer.ucl, > ly = singer.ucl$lower, > uy = singer.ucl$upper, > prepanel = prepanel.ci, > panel = panel.ci, > type="b" > ) > > #################################### > > Any suggestions?Use a panel function that knows about groups, e.g. xyplot(median ~ voice, groups=range, data=singer.ucl, ly = singer.ucl$lower, uy = singer.ucl$upper, prepanel = prepanel.ci, panel = panel.superpose, panel.groups = panel.ci, type="b") If you prefer colored bars, change panel.ci to panel.ci <- function(x, y, ly, uy, subscripts, pch = 16, col.line 'black', ...) { 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 = col.line, length = 0.25, unit = "native", angle = 90, code = 3) panel.xyplot(x, y, pch = pch, col.line = col.line, ...) } Deepayan
Hi Mike, If you're not committed to using a panel function, another option is to use the function lineplot.CI, available in the package sciplot at http://mutualism.williams.edu/sciplot E.g. # Define and generate variables in "long" format range <- vector() voice <- vector() string <- strsplit(as.character(singer$voice.part)," ") for(i in 1:dim(singer)[1]) { range[i] <- string[[i]][1] voice[i] <- string[[i]][2] } # Define function for CI conf.int <- function(x) { st <- boxplot.stats(x) c((st$conf[2]-st$conf[1])/2) } # Plot library(sciplot) lineplot.CI(response=height, x.factor=voice, trace.factor=range, data=singer, fun=median, ci.fun=conf.int) lineplot.CI(response=height, x.factor=voice.part, data=singer, fun=median, ci.fun=conf.int) Manuel On Tue, 2006-06-06 at 00:20 -0300, Mike Lawrence wrote:> Hi all, > > I'm trying to plot error bars in a lattice plot generated with xyplot. Deepayan > Sarkar has provided a very useful solution for simple circumstances > (https://stat.ethz.ch/pipermail/r-help/2005-October/081571.html), yet I am > having trouble getting it to work when the "groups" setting is enabled in > xyplot (i.e. multiple lines). To illustrate this, consider the singer data > generated by the above linked solution previously submitted: > > ##################### > library(lattice) > 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)) > > #now let's split up the voice.part factor into two factors, > singer.ucl$voice=factor(rep(c(1,2),4)) > singer.ucl$range=factor(rep(c("Bass","Tenor","Alto","Soprano"),each=2)) > > #here's Deepayan's previous solution, slightly modified to depict > # the dependent variable (median) and the error bars on the y-axis > # and the independent variable (voice.part) on the x-axis > 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 = pch, ...) > } > > > #this graph works > xyplot(median ~ voice.part, > data=singer.ucl, > ly = singer.ucl$lower, > uy = singer.ucl$upper, > prepanel = prepanel.ci, > panel = panel.ci, > type="b" > ) > > #this one does not (it will plot, but will not seperate the groups) > xyplot(median ~ voice, > groups=range, > data=singer.ucl, > ly = singer.ucl$lower, > uy = singer.ucl$upper, > prepanel = prepanel.ci, > panel = panel.ci, > type="b" > ) > > #################################### > > Any suggestions? >