Adam_S
Adam_S

Reputation: 770

Create stacked bar chart of within group totals

I have the dataset below:

eg_data <- data.frame(
time = c("1","2"), 
size1=c(200, 300))

I add a row to the dataset that is a sum of both time periods:

eg_data <- rbind(eg_data, (data.frame(time="1 + 2", 
size1=sum(eg_data$size1))))
eg_data$time <- factor(eg_data$time, levels = c("1 + 2", "1", "2"))

I create a bar graph

eg_data_bar <- (ggplot() +
geom_bar(data=eg_data, aes(y = size1, x = time, fill = time), 
stat="identity",position='stack'))

eg_data_bar

As it stands now, the graph renders out as three bars which are different colors. I need the bar chart to render as three bars, period 1 is one color, period 2 is another color, and the grouped period 1 + 2 is made up of the two colors from period 1 and period 2.

The problem I'm having is how to define fill within the geom_bar(). When I've done stacked bars before, I always have a third column to use as the fill.

Any help is appreciated.

Upvotes: 1

Views: 156

Answers (1)

Maurits Evers
Maurits Evers

Reputation: 50678

Perhaps something like this?

We start from your initial eg_data data.frame:

eg_data <- data.frame(
    time = c("1","2"),
    size1 = c(200, 300))


library(tidyverse)
eg_data %>%
    mutate(grp = factor(time, levels = 1:2)) %>%
    group_by(time) %>%
    complete(grp) %>%
    replace_na(list(size1 = 0)) %>%
    ungroup() %>%
    spread(time, size1) %>%
    mutate(`1+2` = `1` + `2`) %>%
    gather(time, size, -grp) %>%
    mutate(time = factor(time, levels = c("1", "2", "1+2"))) %>%
    ggplot(aes(time, size, fill = grp)) +
    geom_col(position = "stack")

enter image description here

The key is to add an additional grp variable which we use to fill the bars.

Solution below is solution above, it adds grp to the dataframe and creates the graph as its own object, so it can be called ad-hoc.

eg_data <- eg_data %>% 
mutate(grp = factor(time, levels = 1:2)) %>%
group_by(time) %>%
complete(grp) %>%
replace_na(list(size1 = 0)) %>%
ungroup() %>%
spread(time, size1) %>%
mutate(`1+2` = `1` + `2`) %>%
gather(time, size1, -grp) %>%
mutate(time = factor(time, levels = c("1", "2", "1+2")))

eg_data_graph <-  (ggplot(data = eg_data, aes(time, size1, fill = grp)) +
geom_col(position = "stack"))

eg_data_graph

Upvotes: 2

Related Questions