Monthly Archives: June 2013

Add error bars to a plot in R

So, it’s been a while since I last posted to this blog, but I haven’t forgotten about it.  I’ve just been really busy (aren’t we all?).  I’ve had a few blog posts in mind for a while now,  so I decided to post one so I don’t get too backlogged.

A common feature of scientific figures is the addition of error bars to data points, typically representing 2-standard deviations (SD), 2-standard errors (SE), etc.  When you include them in a graph, they should be easy to read, but not overwhelm the graph.  Here I’ll show you how you can scale the size of the error bars (by size I referring to the cap width of the bars relative to the size of the axis…).I’ve implemented it as a function so that you can reuse it (and improve it!).  If anyone has any suggestions, let me know.  Here goes:

First we will start by creating the function. I’ve added a couple arguments to make the bars “pretty”, but it’s pretty easy to add additional arguments. Note the default values for arguments in the function definition (ie. xcolor = "black", mean that if no xcolor is specifically specified when the function is called, it will default to “black”). You can also see how I calculate the width of the error bar caps: I take the difference between the largest and smallest value on the relevant axis and divide by the “cap.scaling” argument. 50 seems to make a nice sized error bar cap so I set that as the default, but you can use whatever you think is best.
Lastly and most importantly, for Plot_ErrorBars() to work correctly, each argument that doesn’t have a default value MUST be called either by name or listed in the EXACT order as in the function definition. I think there are ways to get around this, but that is for another post 🙂

### Plotting function to plot y- or x-axis error bars
### Filename: Plot_ErrorBars.R
### Notes:
############################################################################

# INPUTS:
# x: x-axis data
# y: y-axis data
# x.err: error bars for x-axis data
# y.err: error bars for y-axis data
# xbar: Whether error bars for x-axis values should be plotted (Default is F)
# ybar: Whether error bars for y-axis values should be plotted (Default is F)
# cap.scaling: scaling factor for size of error bar caps. Default is 50.
# xcolor: line color. (Default is black)
# ycolor: line color. (Default is black)
# lwidth: line width (Default is 1)

# OUTPUTS:
# error bars for x-axis data, y-axis data, or both.

# FUNCTION:
Plot_ErrorBars<-function(x, y, x.err, y.err, xbar = F,
                         ybar = F, cap.scaling = 50, xcolor = "black",
                         ycolor = "black", lwidth = 1, ...){
  ycap.width <- (par("usr")[4] - par("usr")[3])/cap.scaling
  xcap.width <- (par("usr")[2] - par("usr")[1])/cap.scaling
  if(xbar == T){
    for(i in 1:length(x.err)){
      segments(x0 = x[i] + x.err[i], y0 = y[i],
               x1= x[i] - x.err[i],  y1 = y[i],
               lwd = lwidth, col = xcolor)
      segments(x0 = x[i] + x.err[i], y0 = y[i] + ycap.width,
               x1=x[i] + x.err[i],   y1 = y[i] - ycap.width,
               lwd = lwidth, col = xcolor)
      segments(x0 = x[i] - x.err[i], y0 = y[i] + ycap.width,
               x1=x[i] - x.err[i],   y1 = y[i] - ycap.width,
               lwd = lwidth, col = xcolor)
    }
  }
  if(ybar == T){
    for(i in 1:length(y.err)){
      segments(x0 = x[i], y0 = y[i] + y.err[i],
               x1= x[i],  y1 = y[i] - y.err[i],
               lwd = lwidth, col = ycolor)
      segments(x0 = x[i] + xcap.width, y0 = y[i] + y.err[i],
               x1=x[i] - xcap.width,   y1 = y[i] + y.err[i],
               lwd = lwidth, col = ycolor)
      segments(x0 = x[i] + xcap.width, y0 = y[i] - y.err[i],
               x1=x[i] - xcap.width,   y1 = y[i] - y.err[i],
               lwd = lwidth, col = ycolor)
    }
  }
}
# END OF FUNCTION

Now we will use Plot_ErrorBars() with some fake data. I’ll also demonstrate how changing the “cap.scaling” argument changes the cap widths. First I’ll just use the default arguments, and only plot error bars for the y values:

# Create fake data
x1 <- seq(1, 10, 1) + rnorm (length(seq(1, 10, 1)), mean =0, sd= 0.5)
y1 <- seq(1, 10, 1) + rnorm (length(seq(1, 10, 1)), mean =0, sd= 0.5)
x.se <- abs(rnorm(length(seq(1, 10, 1)), mean =0, sd= 0.75))
y.se <- abs(rnorm(length(seq(1, 10, 1)), mean =0, sd= 0.75))
# Plot
plot(x1, y1, pch = 20, cex = 1.5, xlim = c(0,12), ylim = c(0, 12))
Plot_ErrorBars(x1, y1, y.err=y.se, ybar = T)

Here are the results:
default_errorbars

Now I’m going to change some of the default parameters and plot both x and y error bars:

# Plot
plot(x1, y1, pch = 20, cex = 1.5, xlim = c(0,12), ylim = c(0, 12))
Plot_ErrorBars(x1, y1, x.err=x.se, y.err=y.se, xbar = T, ybar = T,
               xcolor = "red", ycolor = "blue", lwidth = 2,
               cap.scaling = 100)

Here are the results. Note that increasing the “cap.scaling” decreases the cap width, and all arguments that don’t have a default need to be specifically defined! Finally, observant R users might notice that at the error bars are plotted on top of the points!  This is an easy fix by re-plotting the points after calling Plot_ErrorBars() using the points() function.user_specified_errorbars

Hope you enjoy this post, and let me know if you have improvements or questions. Also, look for some more posts soon!