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!

Advertisements

One thought on “Add error bars to a plot in R

  1. Sevi

    I just found this and it saved me. I’ve been fighting with various functions from various packages, but I needed something that could simply take a column from a data table for all of x1, y1, e.err, and y.err, which didn’t seem to be possible with the other functions I found. Admittedly I am not particularly great with R (yet), and I was really struggling to do what I wanted (which seemed like it should be straightforward and simple…). Now that I found your function, it’s so easy! I really can’t thank you enough for this.

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s