I'm new to R and statistics. I'm trying to make a grouped barplot with group means and sd error bars, using ggplot. I've imported the dataset from excel (xlsx).

Basically, there're two plants (Var) p & c in two treatments (Temp) c & w and their moisture is measured. I'm trying to make a barplot with the means and errorbars grouped as pc, pw and sc, sw. I'm able to make the barplot, but the errorbars I'm stuck with. When I try to calculate the sd separately and then use it as limits in geom_errorbar, it shows error: aesthetics must be either length 1 or the same as the data (112): ymax, ymin. I really don't know what else to do.

Dummy data -

Var            Temp    moisturep
Purple Teepee  cool    89.01974
Purple Teepee  cool    80.87346
Safari         cool    78.97458
Safari         cool    86.98475
Purple Teepee  warm    98.98734
Purple Teepee  warm    98.76593
Safari         warm    87.98745
Safari         warm    90.45870

Code -

data <- pgpr

temp.mean <- t(tapply(data$moisturep,
                      list(data$Var, data$Temp),
                      mean))

temp.sd <- t(tapply(data$moisturep,
                    list(data$Var, data$Temp),
                    sd))

limits <- aes(ymax = temp.mean + temp.sd,
              ymin = temp.mean - temp.sd)


ggplot(data, 
       aes(fill = data$Temp,
           x = data$Var,
           y = data$moisturep)) +
  geom_bar(position = "dodge", 
           stat = "summary", 
           fun.y = "mean") +
  geom_errorbar(limits, 
                position = position_dodge(0.9),
                width = 0.25)

2 Answers

1
Rui Barradas On

One way of doing it is the following. I compute the means and standard errors first, and put them in an aggregated dataframe.

library(ggplot2)

agg <- aggregate(moisturep ~ Var + Temp, pgpr, mean)
tmp <- aggregate(moisturep ~ Var + Temp, pgpr, sd)
names(tmp)[3] <- "StdErr"
agg <- merge(agg, tmp)
rm(tmp)

ggplot(agg, 
       aes(x = Var,
           y = moisturep,
           fill = Temp)) +
  geom_bar(stat = "identity",
           position = "dodge") +
  geom_errorbar(aes(ymin = moisturep - StdErr, ymax = moisturep + StdErr), 
                position = position_dodge(0.9),
                width = 0.25)

enter image description here

Data in dput format.

pgpr <-
structure(list(Var = structure(c(1L, 1L, 2L, 2L, 1L, 1L, 2L, 
2L), .Label = c("Purple Teepee", "Safari"), class = "factor"), 
Temp = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L), 
.Label = c("cool", "warm"), class = "factor"), 
moisturep = c(89.01974, 80.87346, 78.97458, 86.98475, 
98.98734, 98.76593, 87.98745, 90.4587)), 
class = "data.frame", row.names = c(NA, -8L))
0
Satya On

You don't have to calculate the sd separately.

You can use stat='summary' in the geom_errorbar:

ggplot(data=mtcars, aes(x=gear, y=hp)) + geom_bar(stat='summary') + geom_errorbar(stat='summary', width=.2)