I have a data frame for making a barplot by "question", where bars are grouped by "group" variable. I'd also like to customize the colors of the error bars according to the ci_color column. As specified in df, each lower_ci and upper_ci should get the color in ci_color of the same row, which means each group may not get the same error bar color across questions. However, using the code below I get a strange result -- Group1 and Group2's error bars for Question B are swapped. How can I make sure the error bars correspond to the correct group and get the correct colors?
# Create a new data frame with group_name
df <- data.frame(
question_name = c("A", "A", "A", "B", "B", "B"),
group_name = c("Group1", "Group2", "Group3", "Group1", "Group2", "Group3"),
estimate_weighted = c(20, 22, 24, 25, 28, 30),
lower_ci = c(15, 20, 22, 22, 26, 28),
upper_ci = c(25, 25, 26, 28, 30, 32),
ci_color = c("black", "blue", "red", "blue", "black", "red") # Set colors as intended
)
# Create the ggplot bar plot with grouped bars
ggplot(df, aes(x = factor(question_name), y = estimate_weighted, fill = factor(group_name))) +
geom_bar(stat = "identity", position = position_dodge(0.9)) +
geom_errorbar(
aes(ymin = lower_ci, ymax = upper_ci, color = ci_color),
width = 0.2,
position = position_dodge(0.9)
) +
scale_color_manual(values = c('black', 'blue', 'red')) + # Specify colors explicitly
labs(
x = "Question Name",
y = "Estimate Weighted",
color = "CI Color"
) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
I tried changing the scale_color_manual to be exactly the same as ci_color, but still doesn't solve the problem.
The issue is that your error bars are implicitly grouped (and dodged) by color = ci_color
whereas your bars are grouped by fill = factor(group_name)
. To align the error bars with the bars you have use the same grouping, which could be achieved by explicitly mapping on the the group
aes, i.e. add group = factor(group_name)
to geom_errorbar
.
Moreover, while the colors are assigned in the correct order in your example I would still suggest to use a named vector of colors to ensure that the right colors are assigned to the ci_color
categories.
library(ggplot2)
pal_color <- c("black", "blue", "red")
names(pal_color) <- pal_color
pal_color
#> black blue red
#> "black" "blue" "red"
ggplot(df, aes(
x = factor(question_name),
y = estimate_weighted,
fill = factor(group_name)
)) +
geom_col(position = position_dodge(0.9)) +
geom_errorbar(
aes(
ymin = lower_ci, ymax = upper_ci,
color = ci_color, group = factor(group_name)
),
width = 0.2,
position = position_dodge(0.9)
) +
scale_color_manual(values = pal_color) +
labs(
x = "Question Name",
y = "Estimate Weighted",
color = "CI Color"
) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1)
)