Search code examples
rggplot2errorbar

The Error Bars and the value labels are not getting placed on the Correct Bars in ggplot2


I am trying to add Error bars and label values to the graphs. I am able to add the bars. But they are not getting placed in the exact place which I want. That is each error bar and label value is not getting placed on its corresponding bar. Instead they are mismatched.

The code I used:

Source_Data <-
data.frame(
    key = c(1, 1, 1, 2, 2, 2, 3, 3, 3),
    Product_Name = c(
      "Table",
      "Table",
      "Chair",
      "Table",
      "Bed",
      "Bed",
      "Sofa",
      "Chair",
      "Sofa"
    ),
    Product_desc = c("XX", "XXXX", "YY", "X", "Z", "ZZZ", "A", "Y", "A"),
    sd =c(0.1,0.3,0.4,0.5,0.6,0.7,0.7,0.8,0.5),
    Cost = c(1, 2, 3, 4, 2, 3, 4, 5, 6)

)

Source_Data %>% 
ggplot(aes(Product_Name, Cost)) + 
geom_col(aes(fill = Product_desc), position = position_dodge(preserve = 
"single")) + 
geom_errorbar(aes(ymin=Cost-sd, ymax=Cost+sd)) +
geom_text(aes(label=Cost)) +
facet_wrap(~key, scales = "free_x", strip.position = "bottom") +
theme(strip.placement = "outside") + 
theme_bw()

When the code is run I am not able to place the Error bars and the label values on the correct bars.

Also is there a way to make the graph more interactive? i.e. when i move my cursor over top of the graph the values should get automatically displayed, if required I am happy to post this as a separate question also.


Solution

  • There may be a better approach than I what I provide here, and/or this may not be exactly what you need. Please comment if this resembles what you are looking for.

    I switched your code from position_dodge to position_dodge2 which better centers groups of bars in x position. Also, moved fill = Product_desc to main ggplot call (good practice).

    I consistently set width to .9 for geom_col, geom_errorbar, and geom_text. To get the errorbars to align, I added padding (see: https://github.com/tidyverse/ggplot2/issues/2251). Also, moved text y position to slightly above error bar (Cost+sd and vjust - could be considered elsewhere if preferred).

    For interactivity, maybe consider plotly package. Please describe further exactly what you would like to see in hover behavior.

    Source_Data %>% 
      ggplot(aes(Product_Name, Cost, fill = Product_desc)) + 
      geom_col(position = position_dodge2(width = .9, preserve = "single")) + 
      geom_errorbar(aes(ymin=Cost-sd, ymax=Cost+sd), position = position_dodge2(width = .9, preserve = "single", padding = .5)) +
      geom_text(aes(y=Cost+sd, label=Cost), position = position_dodge2(width=.9), vjust = -1) +
      facet_wrap(~key, scales = "free_x", strip.position = "bottom") +
      theme(strip.placement = "outside") + 
      theme_bw()
    

    Bar plot with error bars and text aligned