I am new to R. I want to graph group data using a "Traditional Bar Chart with Standard Error Bar", like the kind shown here: http://samiam.colorado.edu/~mcclella/ftep/twoGroups/twoGroupGraphs.html Is there a simple way to do this? So far, I have only figured out how to plot the bars using barplot. testdata <- scan(, list(group=0,xbar=0,se=0)) 400 0.36038 0.02154 200 0.35927 0.02167 100 0.35925 0.02341 50 0.35712 0.01968 25 0.35396 0.01931 barplot(testdata$xbar, names.arg=as.character(testdata$group), main="a=4.0", xlab="Group", ylab="xbar") xvalues <- c(0.7, 1.9, 3.1, 4.3, 5.5) arrows(xvalues, testdata$xbar, xvalues, testdata$xbar+testdata$se, length0.4, angle=90, code=3) The best clue I have so far is Rtips #5.9: http://pj.freefaculty.org/R/Rtips.html#5.9 which is what I based my present solution off of. However, I do not understand how this works. It seems like there is no concrete way to determine the arrow drawing parameters x0 and x1 for a barplot. Moreover, the bars seem to be "cut off". [[alternative HTML version deleted]]
Frank E Harrell Jr
2007-Jul-25 16:21 UTC
[R] Constructing bar charts with standard error bars
John Zabroski wrote:> I am new to R. > > I want to graph group data using a "Traditional Bar Chart with Standard > Error Bar", like the kind shown here: > http://samiam.colorado.edu/~mcclella/ftep/twoGroups/twoGroupGraphs.htmlThere are severe problems with dynamite plots such as these. See http://biostat.mc.vanderbilt.edu/DynamitePlots for a list of problems and solutions. Frank> > Is there a simple way to do this? > > So far, I have only figured out how to plot the bars using barplot. > > testdata <- scan(, list(group=0,xbar=0,se=0)) > 400 0.36038 0.02154 > 200 0.35927 0.02167 > 100 0.35925 0.02341 > 50 0.35712 0.01968 > 25 0.35396 0.01931 > > barplot(testdata$xbar, names.arg=as.character(testdata$group), main="a=4.0", > xlab="Group", ylab="xbar") > xvalues <- c(0.7, 1.9, 3.1, 4.3, 5.5) > arrows(xvalues, testdata$xbar, xvalues, testdata$xbar+testdata$se, length> 0.4, angle=90, code=3) > > > The best clue I have so far is Rtips #5.9: > http://pj.freefaculty.org/R/Rtips.html#5.9 which is what I based my present > solution off of. > > However, I do not understand how this works. It seems like there is no > concrete way to determine the arrow drawing parameters x0 and x1 for a > barplot. Moreover, the bars seem to be "cut off". > > [[alternative HTML version deleted]] > > ______________________________________________ > 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. >-- Frank E Harrell Jr Professor and Chair School of Medicine Department of Biostatistics Vanderbilt University
John Zabroski <johnzabroski <at> gmail.com> writes:> > I am new to R. > > I want to graph group data using a "Traditional Bar Chart with Standard > Error Bar", like the kind shown here: > http://samiam.colorado.edu/~mcclella/ftep/twoGroups/twoGroupGraphs.html > > Is there a simple way to do this?[snip]> The best clue I have so far is Rtips #5.9: > http://pj.freefaculty.org/R/Rtips.html#5.9 which is what I based my present > solution off of. > > However, I do not understand how this works. It seems like there is no > concrete way to determine the arrow drawing parameters x0 and x1 for a > barplot. Moreover, the bars seem to be "cut off". >barplot() returns the x values you need for x0 and x1. barplot(...,ylim=c(0,xbar+se)) will set the upper y limit so the bars don't get cut off. Here are three ways to create such a barplot (I will add this to the wiki once it's back on line): (n.b.: the with() command is just a shortcut to avoid having to type testdata$xbar, testdata$group, etc.) ## 1. tweaked version of what you did above testdata <- data.frame(group=c(400,200,100,50,25), xbar= c(0.36038 , 0.35927 , 0.35925 , 0.35712 , 0.35396), se = c(0.02154,0.02167,0.02341,0.01968, 0.01931)) xvals = with(testdata, barplot(xbar, names.arg=group, main="a=4.0", xlab="Group", ylab="xbar",ylim=c(0,max(xbar+se)))) with(testdata, arrows(xvals, xbar, xvals, xbar+se, length=0.4, angle=90, code=3)) ## 2. using the plotCI function from plotrix to draw the ## arrows instead library(plotrix) xvals = with(testdata, barplot(xbar, names.arg=group, main="a=4.0", xlab="Group", ylab="xbar",ylim=c(0,max(xbar+se)))) with(testdata, plotCI(xvals, xbar, liw=0,uiw=se,add=TRUE,pch=NA,gap=FALSE)) ## 3. the most automatic way, using barplot2() from the ## gplots package library(gplots) with(testdata, barplot2(xbar,names.arg=group,main="a=4.0", xlab="Group",ylab="xbar",plot.ci=TRUE, ci.u=xbar+se,ci.l=xbar)) P.S. I hope you're not hoping to infer a statistically significant difference among these groups ... cheers Ben Bolker
John Zabroski wrote:> On 7/25/07, Ben Bolker <bolker at ufl.edu> wrote: > > Thanks a lot! I tried all three and they all seem very dependable. > Also, I appreciate you rewriting my solution and adding elegance. > > Is there a way to extend the tick marks to the ylim values, such that > the yscale ymax tickmark is something like max(xbar+se)? In the > documentation, I thought par(yaxp=c(y0,y1,n)) would do the trick, but > after trying to use it I am not sure I understand what yaxp even does.It took me quite a while to figure this out, I'm not surprised you didn't ... The very easiest way to do this is simply to set ylim to (0,0.4) -- since you probably want to extend the axes upward to a "pretty" number anyway. The other standard way to do this is to use barplot with axes=FALSE and then add the axes yourself, with the ticks specified wherever you want: barplot(...,ylim=c(0,0.4),axes=FALSE) axis(side=1) axis(side=2,at=seq(0,0.4,length=8)) However, I was wondering what was up with yaxp, and why setting it didn't seem to do anything. The answer is lurking in ?par: ## This parameter is reset when a user coordinate system is set ## up, for example by starting a new page or by calling ## 'plot.window' or setting 'par("usr")': 'n' is taken from ## 'par("lab")'. It affects the default behaviour of subsequent ## calls to 'axis' for sides 1 or 3. Thus, when barplot starts up and plots a new set of axes it RESETS par("yaxp"). Thus par(yaxp=...)); barplot(...) doesn't work. However, barplot(...,yaxp=...) does work. It would actually be nice to have an axis style (xaxs,yaxs) that extended the axis out beyond the range of the data until it found pretty labels that extended beyond the data range -- for example, set the range according to xaxs="r", find the pretty axis ticks, and then "add another tick" ... cheers Ben Bolker