specify error bars with ggplot and facet_grid

kumbu picture kumbu · Sep 29, 2015 · Viewed 7.1k times · Source

I have made a graph with facet_grid to visualize the percentage of litium in each group per treatment on each day.

library(ggplot2)
library(Rmisc) 
library(plyr)

mus2 <- summarySE(mus, measurevar="litium", 
                         groupvars=c("treatment", "group", "day"), na.rm = TRUE)

mus2

mus3 <- mus2
mus3$group <- factor(mus3$group)

ms.chl<- ggplot(mus3, aes(x=group, y=litium, fill=treatment)) +
  geom_bar(stat="identity", colour="black") + facet_grid(~day) + theme_bw() 
ms.chl

resulting with this:

enter image description here

For that I have two problems:

I cant make proper error bars for the litium content PER GROUP. I have tried this, but I only get error bars per treatment.

ms.chl + geom_errorbar(aes(ymin=litium-se, ymax=litium+se), size=0.5,   
        width=.25,                    
        position=position_dodge(.9)) +
facet_grid(~day)

enter image description here

I would like to have error bars from the total of each group

and after that, my second question is: is it possible to represent the absolute value per group and the percentage only for each treatment?

Data set (mus):

litium  group   treatment   day
0.009439528 1   Control day1
0.005115057 1   Control day1
0.009742297 1   Control day1
0.016515625 2   Control day1
0.01074537  2   Control day1
0.016300836 2   Control day1
0.009538339 3   Control day1
0.010609746 3   Control day1
0.008928012 3   Control day1
0.009425325 1   Control + bird  day1
0.00561831  1   Control + bird  day1
0.014622517 1   Control + bird  day1
0.017702439 2   Control + bird  day1
0.010545045 2   Control + bird  day1
0.029109907 2   Control + bird  day1
0.013737568 3   Control + bird  day1
0.015174405 3   Control + bird  day1
0.014583832 3   Control + bird  day1
0.009244079 1   Control day2
0.006591033 1   Control day2
0.007592587 1   Control day2
0.013676745 2   Control day2
0.016208676 2   Control day2
0.017593952 2   Control day2
0.014003037 3   Control day2
0.01163581  3   Control day2
0.011643067 3   Control day2
0.009229506 1   Control + bird  day2
0.006423714 1   Control + bird  day2
0.008653163 1   Control + bird  day2
0.012441379 2   Control + bird  day2
0.0204346   2   Control + bird  day2
0.010017788 2   Control + bird  day2
0.009745063 3   Control + bird  day2
0.00967963  3   Control + bird  day2
0.010291306 3   Control + bird  day2
0.009466604 1   Fence   day2
0.019611081 2   Fence   day2
0.006796444 2   Fence   day2
0.018928695 2   Fence   day2
0.007787736 3   Fence   day2
0.009409897 3   Fence   day2

Answer

Sam Dickson picture Sam Dickson · Sep 29, 2015

The first and easiest solution would be to make your bar plot side-by-side instead of stacked. Then the only thing you need to change in your code is to add position="dodge" to your geom_bar() and run the rest of your code as you have it. This has the added benefit of being able to compare the heights of the different bars directly and avoids placing error bars in the middle of a bar.

ms.chl<- ggplot(mus3, aes(x=group, y=litium, fill=treatment)) +
  geom_bar(stat="identity", colour="black",position="dodge") + 
  facet_grid(~day) + theme_bw() 
ms.chl + geom_errorbar(aes(ymin=litium-se, ymax=litium+se), size=0.5,   
    width=.25,position=position_dodge(.9)) +
  facet_grid(~day)

enter image description here

To add error bars on a stacked bar plot, you have to have make sure the bars are centered on the cumulative sum of litium. For this, you can use cumsum() within ave():

mus3 <- within(mus3,lit2 <- ave(litium,group,day,FUN=cumsum))

Then use lit2 instead of litium when you call geom_errorbar() and don't dodge.

ms.chl<- ggplot(mus3, aes(x=group, y=litium, fill=treatment)) +
  geom_bar(stat="identity", colour="black") + facet_grid(~day) + theme_bw() 

ms.chl + geom_errorbar(aes(ymin=lit2-se, ymax=lit2+se), size=0.5,   
                       width=.25) + facet_grid(~day)

enter image description here

And if you just want the error bars for the group, then you have to get the errors for the whole group and not the group within treatment, but you can't just add that straight to the means based on the whole group, because those are means and the stacked bar plot has the sum of the means, so you have to sum the means from mus3.

musgroup <- summarySE(mus, measurevar="litium", 
                      groupvars=c("group", "day"), na.rm = TRUE)

musgroupsum <- ddply(mus3,.(group,day),summarize,lit2 = sum(litium))

mus4 <- merge(musgroup,musgroupsum)

ms.chl<- ggplot() +
  geom_bar(data=mus3, aes(x=group, y=litium, fill=treatment),
           stat="identity", colour="black") + facet_grid(~day) + theme_bw() 

ms.chl + geom_errorbar(data=mus4,aes(x=group,ymin=lit2-se, ymax=lit2+se),
                       size=0.5, width=.25)

enter image description here

At this point, though, it starts getting a little nonsensical. The stacked means are not the group means--they are the sum of the group means, but the error is for the group mean. When you look at the figure the error bars will seem smaller in relation to the mean they represent because they are centered much higher than they ought to be. It seems like what you are looking for is a representation of the group mean that allows you to see the contribution of each of the treatments to that group mean. One way to show this is to scale the bar plot size so that the cumulative sum is centered on the proper mean for each of the groups.

mus3 <- within(mus3,lit3 <- ave(litium,group,day,FUN=function(x) x/length(x)))

ms.chl<- ggplot() +
  geom_bar(data=mus3, aes(x=group, y=lit3, fill=treatment),
           stat="identity", colour="black") + facet_grid(~day) +
  theme_bw() + ylab("litium")

ms.chl + geom_errorbar(data=mus4,aes(x=group,ymin=litium-se, ymax=litium+se),
                       size=0.5,width=.25)

enter image description here