How to Stack Error Bars in a Stacked Bar Plot Using Geom_Errorbar

How to stack error bars in a stacked bar plot using geom_errorbar?

What is happening here is that ggplot is not stacking the error bars (they would have to be summed) so you will have to do that by hand (and it seems that Hadley thinks that this is not a good idea and wil not add this functionality).

So doing by hand:

DF$ci_l[DF$response == "Yes, part of the journey"] <- with(DF,ci_l[response == "Yes, part of the journey"] +
ci_l[response == "Yes, entire the journey"])

DF$ci_u[DF$response == "Yes, part of the journey"] <- with(DF,ci_u[response == "Yes, part of the journey"] +
ci_u[response == "Yes, entire the journey"])

Now:

ggplot(DF, aes(x=factor(year), y=proportion)) +
facet_grid(. ~ sex) +
geom_bar(stat="identity",aes(fill=response)) +
geom_errorbar(aes(ymin= ci_l,
ymax= ci_u),
width=.2, # Width of the error bars
position="identity")

Sample Image

How to organize error bars to relevant bars in a stacked bar plot in ggplot?

You can stack it, but it's hard to read the error bars. @kath made a good point about interpretability. Maybe you want to consider plotting them side by side?

library(gridExtra)

# side by side
side_p <- ggplot(dff, aes(x=month, y=o2, fill=site))+
geom_col(color="black", width=0.6,position=position_dodge(width=0.6))+
geom_errorbar(aes(ymin=o2, ymax=o2+se), width=0.2,position=position_dodge(width=0.6))

# calculate the new y
dff2 = dff %>% arrange(desc(site)) %>% group_by(month) %>% mutate(newy=cumsum(o2))
stacked_p <- ggplot(dff2, aes(x=month, y=o2, fill=site))+
geom_col(color="black", width=0.6,position=position_stack(vjust=1))+
geom_errorbar(inherit.aes = FALSE,aes(x=month,ymin=newy, ymax=newy+se), width=0.2)
#together
grid.arrange(side_p,stacked_p)

Sample Image

How to make a stacked bar chart with overall error bar?

The problem is that geom_bar is constructing the histogram for you, and thus doesn't have access to all of the other columns in your dataframe. Here I use geom_col to construct the histogram myself, including calculating the total count and standard deviation for each group.

Another option (df2, second plot below) is to replace the mutate with a summarize, and pass that as a separate dataframe to geom_errorbar (and keep your geom_bar). I would prefer this, as it only draws the error bars once per bar, instead of overdrawing them for each color.

library(dplyr, warn.conflicts = FALSE)
library(ggplot2)

df <- diamonds %>% group_by(clarity, color) %>%
summarize(count = n()) %>%
group_by(clarity) %>%
mutate(sd = sqrt(var(count)), count_total = sum(count)) %>%
ungroup()
#> `summarise()` has grouped output by 'clarity'. You can override using the `.groups` argument.

ggplot(df, aes(clarity, y=count, fill=color, ymin=count_total-sd, ymax = count_total+sd)) +
geom_col()+
geom_errorbar()

Sample Image

df2 <- diamonds %>% group_by(clarity, color) %>% 
summarize(count = n()) %>%
group_by(clarity) %>%
summarize(sd = sqrt(var(count)), count_total = sum(count)) %>%
ungroup()
#> `summarise()` has grouped output by 'clarity'. You can override using the `.groups` argument.

ggplot(diamonds, aes(clarity, fill=color)) +
geom_bar()+
geom_errorbar(data = df2, aes(clarity, ymin=count_total-sd, ymax = count_total+sd), inherit.aes = FALSE)

Sample Image

Created on 2021-10-10 by the reprex package (v2.0.1)

Error bars incorrectly positioned in a stacked bar graph in r

This should do what you want:

Basically, you have to add your Mean values to fit in the stack, while keeping the order used by geom. There may be more efficient ways to generate tmp but this gets across the idea.

tmp <- unlist( lapply( seq(0,138,by=6), function(x) c(
df$Mean[3+x]+df$Mean[6+x]+df$Mean[2+x]+df$Mean[1+x],
df$Mean[3+x]+df$Mean[6+x]+df$Mean[2+x],
df$Mean[3+x],
df$Mean[3+x]+df$Mean[6+x]+df$Mean[2+x]+df$Mean[1+x]+df$Mean[5+x]+df$Mean[4+x],
df$Mean[3+x]+df$Mean[6+x]+df$Mean[2+x]+df$Mean[1+x]+df$Mean[5+x],
df$Mean[3+x]+df$Mean[6+x] ) ) )
df <- cbind( df, Mean_2=tmp )
ggplot(df, aes(x=Treatment, y=Mean, fill=variable))+
facet_wrap(~Gen)+geom_bar(stat="identity", colour="black")+
ggtitle("G")+xlab("Stress Treatment")+ylab("Variable level")+
geom_errorbar(aes(ymin=Mean_2-se, ymax=Mean_2+se), size=0.5,
width=0.3, position="identity", colour="black")

Result:

Sample Image

Vertically error bars allignment, stacked bars plot ggplot

You should add value of lower stack to the value of upper stack

library(ggplot2)

type96<- c("co2_96","NetCH4_96h", "co2_96", "NetCH4_96h", "co2_96", "NetCH4_96h", "co2_96", "NetCH4_96h", "co2_96", "NetCH4_96h", "co2_96", "NetCH4_96h", "co2_96", "NetCH4_96h", "co2_96", "NetCH4_96h", "co2_96", "NetCH4_96h", "co2_96", "NetCH4_96h", "co2_96", "NetCH4_96h", "co2_96", "NetCH4_96h", "co2_96","NetCH4_96h")
gp96<- c( 13.066667,4.283333,11.783333,3.983333,12.616667,4.4,12.383333,4.3,12.783333,4.566667,12.466667,4.383333,11.533333,4.066667,12.816667,4.533333,12.92,4.56,12.516667,4.25,13.4,4.366667,12.45,4.316667,12.366667,4.233333)
sd<- c(2.1096603, 0.8232051, 1.553598, 0.7386925, 1.2448561, 0.6870226, 2.0311737, 0.8579044, 1.3585532, 0.7033254, 1.5933194, 0.7386925, 2.5303491, 1.1500725, 1.1373947, 0.5715476, 0.9066422, 0.5176872, 0.7026142, 0.3937004, 0.9570789, 0.6345602, 1.3003846, 0.6242329, 1.0875048, 0.3669696)


dfch97 <- data.frame(type96, gp96, sd)

dfch97$sample96 <- rep(1:13, each = 2)

dfch97$type96=as.factor(dfch97$type96)

for (i in 1:nrow(dfch97)){
if(dfch97[i, 'type96'] == "co2_96"){
dfch97[i,'u_conf'] <- dfch97[i,'gp96'] + dfch97[i+1, 'gp96'] + dfch97[i,'sd']
dfch97[i,'l_conf'] <- dfch97[i,'gp96'] + dfch97[i+1, 'gp96'] - dfch97[i,'sd']
} else {
dfch97[i,'u_conf'] <- dfch97[i,'gp96'] + dfch97[i,'sd']
dfch97[i,'l_conf'] <- dfch97[i,'gp96'] - dfch97[i,'sd']
}
}

ggplot(data=dfch97,aes(y=gp96,x=sample96,fill=type96))+
geom_bar(position = position_stack(),stat="identity") +
geom_errorbar(aes(ymin=l_conf, ymax=u_conf),
position=position_dodge(), stat="identity",width=0.7,size=0.01)

Sample Image

Error bars incorrectly positioned in a stacked bar graph (r)

I think this happens because the variable is plotted top to bottom on the y-axis, but sum in cumsum(value) is calculated assuming they are plotted bottom to top.

I reordered the data frame before taking the sum then it works:

x <- data.frame(Period = c("Mon","Tue","Wed","Thu","Fri","Sat","Sun"), Sample = c("Day","Day","Day","Day","Day","Day","Day"), "12AM-6AM" = c(23.14,16.43,16,22.71,36.86,87.14,110.71), "6AM-12PM" = c(16.14,20.86,18.43,16.71,15.14,14.29,16), "12PM-6PM" = c(26.86,23.71,25.57,23.43,35.29,38,30), "6PM-12AM" =c(35.86,34.14,31.71,36.43,45.57,44,27.14))

library(tidyverse)
library(reshape2)
#>
#> Attaching package: 'reshape2'
#> The following object is masked from 'package:tidyr':
#>
#> smiths

mx <- melt(x, id.vars=1:2)
mx <- mx %>%
mutate(sd = c( 5.4, 2.7, 4.7, 4.4, 8.2, 13.2, 20.7,
5.6, 2.3, 5.4, 5.5, 1.6, 4.1, 3.1,
5.2, 5.6, 5.9, 3.5, 6.3, 4.5, 6.9,
3.5, 6.0, 5.9, 6.2, 8.2, 9.0, 2.4)
) %>%
group_by(Period) %>%
arrange(desc(variable)) %>%
mutate(
pos = cumsum(value),
upper = pos + sd/2,
lower = pos - sd/2
) %>%
ungroup()

days<-c("Mon", "Tue", "Wed","Thu","Fri", "Sat", "Sun")
ggplot(mx, aes(x=Period, y=value, fill=variable), xLabels=NA) +
geom_bar(stat="identity") +
facet_grid(~Sample) + geom_errorbar(aes(ymin = lower, ymax = upper),
width = .2, col = "red") +
theme_bw() + scale_x_discrete(limits = days) +
xlab(" Day of the Week") + scale_fill_grey() +
ylab ("Number of calls")

Sample Image

Created on 2018-11-10 by the reprex package (v0.2.1)



Related Topics



Leave a reply



Submit