Thanks to the ten kind souls who answered my question, which was:
> Suppose I have a dataset like:
>
> case before after
> 1 -1 2.3
> 2 1.2 2.9
> 3 3 1
> 4 2 -1.5
> (etc.; N=20 cases)
>
> I would like to produce a plot with N vertical bars (possibly touching, or
> possibly separated with a little space, whichever looks better). The
> horizontal axis runs from 1 to N, and the vertical axis runs over the
range
> of the data (from -3 to +3, in fact). Each vertical bar would go from
> min(before,after) to max(before,after) for the row (case) it represents.
> Then, if after > before, I would leave the bar unshaded, but if before >
> after, I would shade in the bar.
...
Most proposed solutions involved using segments, arrows, or polygons, and
all would have worked. I decided to go with Shawn Boles' suggestion:
> test.df<-data.frame(round(runif(20,-3,3),2),round(runif(20,-3,3),2))
> names(test.df)<-c("before","after")
> test.df
before after
1 1.92 0.57
2 -2.51 1.23
3 -2.21 -2.89
4 -2.90 -1.37
5 0.03 -1.82
6 -1.73 0.34
7 -2.46 1.36
8 -1.27 2.01
9 1.75 2.99
10 -1.44 0.76
11 1.38 -1.63
12 -1.71 -1.33
13 0.28 0.02
14 1.91 -0.08
15 0.32 -1.77
16 -2.68 -1.75
17 -0.99 1.92
18 1.34 -1.81
19 2.99 -0.42
20 -0.38 -1.99
> attach(test.df)
> # modified errbar function to do what you want
> errbar
function(x, y, yplus, yminus, cap = 0.015, xlab =
as.character(substitute(x)),
ylab = as.character(substitute(y)), add = F, lty = 1, ylim, lwd = 1,
...)
{
if(missing(ylim))
ylim <- range(y, yplus, yminus, na.rm = T)
if(!add)
plot(x, y, ylim = ylim, xlab = xlab, ylab = ylab, ...)
xcoord <- par()$usr[1:2]
arrows(x, yminus, x, yplus, lty = lty, lwd = lwd)
smidge <- (cap * (xcoord[2] - xcoord[1]))/2
segments(x - smidge, yminus, x + smidge, yminus, lwd = lwd)
segments(x - smidge, yplus, x + smidge, yplus, lwd = lwd)
}
>
> errbar(1:20,rep(0,20),after,before,cap=0)
> # produces the plot with arrowhead instead of shading.
|