I am trying to add SEM errorbars to a ggplot clustered bar chart but they are all appearing on top of eachother in the middle bar of each cluster, rather than over the corresponding bar. I am not sure how to fix this. I have tried manually fixing the dodge applied. code to create sample data:
id <- 1:15
role <- rep(c("Admin", "User","bug"), each = 5) # Example roles
Questions <- factor(c("blue", "black", "pink", "red", "gold"), levels = c("blue", "black", "pink", "red", "gold"))
Answers <- factor(1:5, levels = 1:5)
set.seed(123) # For reproducibility
data <- expand.grid(id = id, Questions = Questions)
data$role <- rep(role, each = length(Questions))
data$Answers <- factor(sample(1:5, nrow(data), replace = TRUE), levels = 1:5)
data <- data %>%
select(id, role, Questions, Answers)
the code I am using to create the plot:
dodge <- position_dodge(width = 0.9)
data %>%
group_by(Questions,role)%>%
summarise(mean_score = mean(as.numeric(Answers)),
sem = sd(as.numeric(Answers)) / sqrt(n()),.groups = "keep")%>%
ggplot(aes(reorder(Questions,-mean_score), mean_score))+
geom_col(aes(fill = role), position = "dodge")+
geom_errorbar(aes(ymin = mean_score - sem, ymax = mean_score + sem), width = 0.2, position = "dodge") +
xlab("")+
ylab("Mean score")+
coord_flip()+
theme_classic()+
scale_fill_viridis_d()
(I realise that the repex doesn't generate bars for every group in every category, the issue is still clear in the categories with multiple bars though)
Add a group = role
inside the aesthetics for the errorbar (the fill
argument creates the group for the columns).
If you're specifying the dodge
as a variable, make sure you include it without quotations.
dodge <- position_dodge(width = 0.9)
data %>%
group_by(Questions, role) %>%
summarise(
mean_score = mean(as.numeric(Answers)),
sem = sd(as.numeric(Answers)) / sqrt(n()), .groups = "keep"
) %>%
ggplot(aes(reorder(Questions, -mean_score), mean_score)) +
geom_col(aes(fill = role), position = dodge) +
geom_errorbar(
aes(
ymin = mean_score - sem,
ymax = mean_score + sem, group = role
),
width = 0.2, position = dodge
) +
xlab("") +
ylab("Mean score") +
coord_flip() +
theme_classic() +
scale_fill_viridis_d()