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?
>