0

I want to plot a stacked bar plot for my data frame which is shown below:

structure(list(Insured_Age_Group = c(1, 1, 2, 2, 3, 3, 4, 4, 
5, 5, 6, 6, 7, 7), Policy_Status = c("Issuance", "Surrended", 
"Issuance", "Surrended", "Issuance", "Surrended", "Issuance", 
"Surrended", "Issuance", "Surrended", "Issuance", "Surrended", 
"Issuance", "Surrended"), Deposit_mean = c(3859543.73892798, 
3456815.07390356, 4013324.11384503, 3472236.67594808, 3970469.37408863, 
3525624.68661194, 4405204.3601121, 3972720.91952494, 4379252.01763646, 
3927956.07114074, 3816234.23370925, 3428881.46975029, 3342252.39385489, 
2712813.93450449), Insurance_mean = c(1962975.48419977, 1456418.88629993, 
2003323.06714903, 1623189.55193443, 2665058.97077804, 2211482.53333601, 
3033051.58298144, 2553113.08079923, 3579542.94373979, 3021601.37830552, 
4338039.6868955, 3613388.25638188, 4806849.35326484, 3715049.4317553
)), row.names = c(NA, -14L), groups = structure(list(Insured_Age_Group = c(1, 
2, 3, 4, 5, 6, 7), .rows = structure(list(1:2, 3:4, 5:6, 7:8, 
    9:10, 11:12, 13:14), ptype = integer(0), class = c("vctrs_list_of", 
"vctrs_vctr", "list"))), row.names = c(NA, 7L), class = c("tbl_df", 
"tbl", "data.frame"), .drop = TRUE), class = c("grouped_df", 
"tbl_df", "tbl", "data.frame"))

   Insured_Age_Group Policy_Status Deposit_mean Insurance_mean
               <dbl> <chr>                <dbl>          <dbl>
 1                 1 Issuance          3859544.       1962975.
 2                 1 Surrended         3456815.       1456419.
 3                 2 Issuance          4013324.       2003323.
 4                 2 Surrended         3472237.       1623190.
 5                 3 Issuance          3970469.       2665059.
 6                 3 Surrended         3525625.       2211483.
 7                 4 Issuance          4405204.       3033052.
 8                 4 Surrended         3972721.       2553113.
 9                 5 Issuance          4379252.       3579543.
10                 5 Surrended         3927956.       3021601.
11                 6 Issuance          3816234.       4338040.
12                 6 Surrended         3428881.       3613388.
13                 7 Issuance          3342252.       4806849.
14                 7 Surrended         2712814.       3715049.

What I want to do: I want to plot a bar plot for each Insured_age. So for example for insured age 1, we have two barplot side by side (one for Issuance and one for Surrended). I also want each of these bar plots divided into two sections, one part for Deposit_mean and one for Insurance_mean. So in the end, I get a graph like the one shown below (Sorry, I had to draw a line with a pen manually to show the stack in each section. Numbers on the image are just an example):

enter image description here

I tried the approach explained in this link Stacked bar chart with group by and facet but I wasn't able to make what I want.

Ross_you
  • 881
  • 5
  • 22
  • This may be helpful: https://stackoverflow.com/questions/12715635/ggplot2-bar-plot-with-both-stack-and-dodge – Will Oldham Nov 26 '20 at 02:18
  • @WillOldham unfortunately not. It doesn't include two bar plot side by side and missing two group variables. – Ross_you Nov 26 '20 at 02:37

2 Answers2

1

You could reshape your data and use facet_grid. Alternatively, you could combine the two categories into a single variable with paste and use that on the x-axis. Here are examples. Obviously you'll need to rotate axis labels to cleanup, etc.

library(tidyverse)

tmp <- dat %>% pivot_longer(3:4)

ggplot(tmp, aes(Policy_Status, value, fill=name)) +
  geom_col() +
  facet_grid(.~Insured_Age_Group) +
  theme_classic()

tmp <- tmp %>%
       mutate(grp = paste(Insured_Age_Group, Policy_Status))

ggplot(tmp, aes(grp, value, fill=name)) +
  geom_col() +
  theme_classic()

Vincent
  • 15,809
  • 7
  • 37
  • 39
0

The problem is that you can't apparently combine two position arguments for geom_col, which is discussed by the question I referenced. In addition to facet_grid and x = interaction(Insured_Age_Group, Policy_Status), you can also plot two different geom_col arguments:

df <- 
  df %>% 
  pivot_longer(contains("_mean"), names_to = "Means", values_to = "Value")

ggplot(df) +
  aes(y = Value) +
  geom_col(data = subset(df, Policy_Status == "Issuance"), 
           aes(x = Insured_Age_Group + 0.2, fill = Policy_Status, alpha = Means), 
           width = 0.4, 
           color = "black") +
  geom_col(data = subset(df, Policy_Status == "Surrended"), 
           aes(x = Insured_Age_Group - 0.2, fill = Policy_Status, alpha = Means), 
           width = 0.4, 
           color = "black") +
  labs(x = "Insured Age Group") +
  scale_alpha_manual(values = c(0.5, 1)) +
  theme_bw()

Instead of alpha, you can probably set fill = interaction(Policy_Status, Means) as well.

Will Oldham
  • 704
  • 3
  • 13