My aim is to do a basic bar chart where the data comes from two data frames that have the same variables. The plot should look like the one below, but without the two shortcomings. There should be legends for the data frames, and the error bars should be in the middle of the bars. Do you know how to make it? Below is the code that produced that plot, and I don't think bind_rows is the optimal solution here.

The code ↓
bind_rows(B, C, .id = "id") %>%
filter(question %in% c("Q1", "Q2")) %>%
ggplot(aes(x = question, y = mean)) +
geom_bar(aes(fill = id), stat = "identity", position = "dodge2", width = 0.5) +
geom_errorbar(aes(ymin = mean - sd, ymax = mean + sd, width = 0.1, colour = id)) +
coord_flip()
The data frames ↓
structure(list(question = c("Q1", "Q10", "Q11", "Q12", "Q2",
"Q3", "Q4", "Q5", "Q6", "Q7", "Q8", "Q9"), n = c(204L, 204L,
204L, 204L, 204L, 204L, 204L, 204L, 204L, 204L, 204L, 204L),
mean = c(5.22549019607843, NA, 4.95098039215686, 4.39705882352941,
5.47058823529412, 5.51470588235294, 4.50490196078431, 4.92647058823529,
4.40686274509804, 5.56862745098039, 5.56372549019608, 5.23529411764706
), sd = c(1.1524816893289, NA, 1.31214449357814, 1.5422430010719,
1.12039650223724, 1.15104553532809, 1.37714471881058, 1.34621721218454,
1.30030385262334, 0.871099231072865, 0.830963499839951, 1.36945187401243
)), row.names = c(NA, 12L), class = c("tbl_df", "tbl", "data.frame"
))
structure(list(question = c("Q1", "Q10", "Q11", "Q12", "Q2",
"Q3", "Q4", "Q5", "Q6", "Q7", "Q8", "Q9"), n = c(13L, 13L, 13L,
13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 13L), mean = c(5.38461538461539,
4.38461538461539, 4.69230769230769, 4.30769230769231, 5.15384615384615,
5.38461538461539, 4.76923076923077, 5.30769230769231, 4.53846153846154,
5.61538461538461, 5.69230769230769, 4.92307692307692), sd = c(1.26085034391223,
1.44559454541846, 1.03155347127648, 1.60128153805087, 0.898717034272917,
1.12089707663561, 1.01273936708367, 0.85485041426511, 0.967417922046845,
1.26085034391223, 0.85485041426511, 1.84668795692624)), row.names = c(NA,
12L), class = c("tbl_df", "tbl", "data.frame"))
I think dplyr::bind_rows() works perfectly fine here. To align the grouped bars and the error bars, use position_dodge() for both layers.
bind_rows(B, C, .id = "id") %>%
filter(question %in% c("Q1", "Q2")) %>%
ggplot() +
aes(mean, question, fill = id, xmin = mean - sd, xmax = mean + sd) +
geom_col(position = "dodge2", width = 0.5) +
geom_errorbar(position = position_dodge2(padding = 0.5), width = 0.5) +
theme_minimal()

position_dodge2() is also needed if you want to add additional layers.
last_plot() +
geom_point(position = position_dodge2(width = 0.5))

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With