Minyi Han
Minyi Han

Reputation: 827

How to plot a chart with dual Y, both are bar plot with ggplot2?

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))
      

Upvotes: 0

Views: 47

Answers (1)

AndS.
AndS.

Reputation: 8110

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"))

Upvotes: 1

Related Questions