Reputation: 390
I'm trying to create a stacked barplot with errorbars. The datafile is here: https://github.com/Ginko-Mitten/Experimental.git
library(ggplot2)
Dat1<-Methods_Recovery_Comparison
Volunteer<-as.factor(Dat1$Volunteer)
Method<-as.factor(Dat1$Method)
Phase<-as.factor(Dat1$Phase)
Recovery<-as.numeric(Dat1$Recovery)
SD<-as.numeric(Dat1$SD)
SDU<-Recovery+SD
SDL<-Recovery-SD
Ext<-data.frame(Volunteer,Method,Phase,Recovery,SD,SDU,SDL)
ggplot(Ext,aes(Method))+
geom_bar(aes(weight = Recovery, fill = Phase))+
facet_grid(~Volunteer)+
geom_errorbar(aes(ymax=Recovery+SD,ymin=Recovery-SD))
I would really like:
1. The order of the Phase to be reversed
2. The error-bars to align properly to the bars
Edit: Additional Request: Would it be possible to specifically lighten or make the bar hollow for value of Volunteer 3-> Method 2 -> Phase 3? (The corresponding recovery value is 10.5). That particular value was an anomalous one and would like to highlight it in the description while writing up.
Upvotes: 1
Views: 1792
Reputation: 1
I had the same problem and thanks for the nice answer above, it works nicely for positive only data. In my case the y
values are sometimes also negative, which makes the stack a little bit more complicated: it stacks the columns below and above 0.
The same has also to happen with the positions for the error bars, which means the positive and the negative values have to be stacked (values cumulated) separately.
A little function can do the job:
library(base)
stack_pos <- function(vector){
a <- as.vector(vector, mode= "numeric")
b <- a > 0
a[b] <- rev(cumsum(rev(a[b])))
a[!b] <- rev(cumsum(rev(a[!b])))
a}
and can be put into the dplyr
mutation in the answer above:
library(dplyr)
DF <- df %>% group_by(Volunteer, Method) %>%
mutate(SDpos = stack_pos(Recovery))
Note: because of the the double rev()
in the stack_pos
function the order of levels(DF$Phase)
does not have to be changed anymore.
Upvotes: 0
Reputation: 16178
The creator of ggplot2
is not a big fan of error bars on stacked barchart (see: https://github.com/tidyverse/ggplot2/issues/1079) so there is no convenient way implemented in ggplot2
to do that.
The trick is to calculate the y position of the error bar in the stack. Here I used dplyr
to create new column in function of Volunteer and Method that will cumulative add Recovery in order to get the y position for each error bar:
library(dplyr)
DF <- df %>% group_by(Volunteer, Method) %>%
mutate(Phase = factor(Phase, levels = c("Part3","Part2","Part1"))) %>%
mutate(SDpos = cumsum(Recovery))
# A tibble: 27 x 6
# Groups: Volunteer, Method [9]
Volunteer Method Phase Recovery SD SDpos
<chr> <chr> <fct> <dbl> <dbl> <dbl>
1 P1 Method1 Part1 50.6 0.1 50.6
2 P1 Method1 Part2 15.4 1.2 66
3 P1 Method1 Part3 8.8 2.1 74.8
4 P1 Method2 Part1 50.6 0.1 50.6
5 P1 Method2 Part2 15.4 1.2 66
6 P1 Method2 Part3 14.6 2.9 80.6
7 P1 Method3 Part1 50.6 0.1 50.6
8 P1 Method3 Part2 14.6 1.9 65.2
9 P1 Method3 Part3 16.6 2.3 81.8
10 P2 Method1 Part1 25.8 0.1 25.8
# … with 17 more rows
Then, I will make the stacked bargraph and add geom_errorbar
based on the SDpos column I made (it will be my y values):
library(ggplot2)
ggplot(DF, aes(x = Method, y = Recovery, fill = Phase))+
geom_col()+
facet_wrap(.~Volunteer) +
scale_fill_discrete(breaks = c("Part1","Part2","Part3"))+
geom_errorbar(aes(ymin = SDpos-SD, ymax = SDpos+SD), width = 0.2)
Does it look what you are trying to get ?
Upvotes: 2