Using ggplot2 stat_summary with geom col to create distinct sum bar

Viewed 288

I am trying to make a barplot with a summary bar Total showing the sum of two groups: Pulses, Total and Soybeans.

I know it is possible to achieve it by pre-processing the data to get the sum as a summary by group, I am looking for a stat_summary solution. I am not very familiar with stat_summary(), any advice is welcome as I might have overlooked something...

Reprex:

Data:

df <- structure(list(Year = c(2015L, 2016L, 2017L, 2015L, 2016L, 2017L
), Item = c("Soybeans", "Soybeans", "Soybeans", "Pulses, Total", 
"Pulses, Total", "Pulses, Total"), Value = c(884688L, 829166L, 
960640L, 2219455L, 2354696L, 2683772L)), row.names = c(NA, -6L
), class = "data.frame")

What I've tried so far:

library(ggplot2)

ggplot(data = df, aes(x = Year, y = Value)) +
  stat_summary(
    fun = sum,
    geom = "col",
    position = position_dodge(width = 0.95),
    aes(fill = "Total")
  ) +
  geom_col(
    position = position_dodge(width = 0.95),
    aes(fill = Item)
  )

enter image description here

As you can see, the Total bar does not appear as a 3rd distinct bar. Is it possible to achieve this while keeping the two others and without pre-processing the data?

Expected output:

library(dplyr)
df %>% 
  group_by(Year) %>% 
  summarise(Value = sum(Value), Item = "Total") %>% 
  bind_rows(., df) %>% 
  ggplot(data = ., aes(x = Year, y = Value, fill = Item)) +
  geom_col(position = "dodge")

enter image description here

1 Answers

You need to use position_nudge(x = ..) on the total column, and set the barwidth accordingly, for example:

library(ggplot2)

barwidth = 0.3
n = length(unique(df$Item))

ggplot(data = df, aes(x = Year, y = Value)) +
  stat_summary(
    fun = sum,
    geom = "col",
    position = position_nudge(x = -1.5*barwidth),
    aes(fill = "Total"),
    width = barwidth
  ) +
  geom_col(
    position = position_dodge(),
    aes(fill = Item),
    width= barwidth * n
  )

enter image description here

Related