Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error bars for barplot only in one direction

Is it possible to adjust errorbars in ggplot2 so that they are plotted only in one direction (e.g. only upwards but not downwards)?

df <- data.frame(trt = factor(c(1, 1, 2, 2)), resp = c(1, 5, 3, 4),
                 group = factor(c(1, 2, 1, 2)), se = c(0.1, 0.3, 0.3, 0.2))
df2 <- df[c(1,3), ]

limits <- aes(ymax = resp + se, ymin = resp - se)
dodge <- position_dodge(width = 0.9)

p <- ggplot(df, aes(fill = group, y = resp, x = trt))
p + geom_bar(position = dodge, stat = "identity") +
    geom_errorbar(limits, position = dodge, width = 0.25)

Rplot

like image 543
jokel Avatar asked Dec 20 '14 22:12

jokel


2 Answers

An easy work-around would be to plot the error bars first:

p +
  geom_errorbar(limits, position = dodge, width=0.25) +
  geom_bar(position = dodge, stat = "identity")

enter image description here

like image 183
Henrik Avatar answered Oct 13 '22 12:10

Henrik


Henriks answer works if all of the bars are larger than the error bars. If you have error bars that are larger than your data bars, however, the tail end of the 'bottom' tail (negative error bar for positive data bar or vice versa) will be seen because it will cross the 0 y axis. If all of your data are in the same direction, you can set your limits ymin equal to 0.

The problem with this approach is that if you have mixed data bars (some positive and some negative) you can't set a limit to 0. For example, if the original data were:

df <- data.frame(trt = factor(c(1, 1, 2, 2)), resp = c(1, 5, -3, 4),
             group = factor(c(1, 2, 1, 2)), se = c(2, 0.3, 4, 0.2))
df2 <- df[c(1,3), ]

limits <- aes(ymax = resp + se, ymin = resp - se)
dodge <- position_dodge(width = 0.9)

p <- ggplot(df, aes(fill = group, y = resp, x = trt))
p + geom_errorbar(limits, position = dodge, width = 0.25) +
    geom_bar(position = dodge, stat = "identity") 

The resulting plot would have error bars that extend beneath trt 1, group 1 and above trt 2, group1.

This can be fixed by adjusting the limit statment with an ifelse() clause:

limits <- aes(ymax = ifelse(resp>0,resp + se,resp/2),
              ymin = ifelse(resp<0,resp - se,resp/2))

p + geom_errorbar(limits, position = dodge, width = 0.25) +
    geom_bar(position = dodge, stat = "identity") 

In this case, if the data are positive, the error bar max remains as normal, but the error bar min is adjusted to half of the databar height, so it remains hidden behind the databar.

like image 25
John DeWitt Avatar answered Oct 13 '22 12:10

John DeWitt