Home > Software engineering >  How to plot a chart with dual Y, both are bar plot with ggplot2?
How to plot a chart with dual Y, both are bar plot with ggplot2?

Time:02-17

I would like to plot a chart with dual Y, both are bar plot with ggplot2, and both bar with its own error bar and label, the following code fails. The bars overlaped, and the labels can not be displayed.

Thanks a lot. enter image description here

df<- structure(list(dose = structure(1:3, .Label = c("0.5", "1", "2"
), class = "factor"), mean1 = c(13.23, 22.7, 26.06), sd1 = c(0.1, 
0.2, 0.3), label = c("a", "b", "c"), mean2 = c(7.98, 16.77, 26.14
), sd2 = c(0.01, 0.2, 0.3), label2 = c("a", "b", "c")), row.names = c(NA, 
-3L), class = "data.frame")

ggplot(df,aes(x = dose, fill = dose)) 
  geom_bar(aes(y = mean1), position = 'dodge', stat="identity", width=.4)  
  geom_bar(aes(y = mean2/5), position = 'dodge', stat="identity", width=.4) 
  scale_y_continuous(sec.axis = sec_axis(~. *5, name = "mean2")) 
  geom_errorbar(aes(ymin = mean1, ymax = mean1   sd1), width=.07, 
    position=position_dodge(0.4))  
  geom_errorbar(aes(ymin = mean2, ymax = mean2   sd2), width=.07, 
    position=position_dodge(0.4))
  geom_text(aes(y =mean1   sd1, label = label1),vjust = -0.5, position=position_dodge(0.4))
  geom_text(aes(y =mean2   sd2, label = label2,),vjust = -0.5, position=position_dodge(0.4))
      

CodePudding user response:

Is this what you are looking for? You just need to restructure your data so that it can be dodged by group.

  
bind_rows(
  df |>
    select(dose, label, mean = mean1, sd = sd1) |>
    mutate(group = 1),
  
  
  df |>
    select(dose, label, mean = mean2, sd = sd2) |>
    mutate(group = 2,
           mean = mean/5)
) |>
  ggplot(aes(x = dose, fill = dose, group = group)) 
  geom_bar(aes(y = mean), position = 'dodge', stat="identity", width=.4) 
  geom_errorbar(aes(ymin = mean, ymax = mean   sd), width=.07, 
    position=position_dodge(0.4))  
  geom_text(aes(y =mean   sd, label = label),vjust = -0.5, position=position_dodge(0.4)) 
  scale_y_continuous(sec.axis = sec_axis(~. *5, name = "mean2"))

  • Related