Search code examples
rggplot2bar-chartfacet

How can I make a faceted bar chart use stacked bars?


I'm sure I'm missing something obvious here, but have tried a million different iterations and can't seem to find the right recipe. I'm working with survey data and faceting it in a facet_grid, which is now working nicely:

# ingest some data
df <- structure(list(Q52_bin = structure(c(3L, 2L, 2L, 2L, 2L, 2L), .Label = c("low", 
"medium", "high"), class = "factor"), Q53_bin = structure(c(2L, 
3L, 2L, 2L, 2L, 2L), .Label = c("low", "medium", "high"), class = "factor"), 
    Q57_bin = structure(c(2L, 2L, 2L, 2L, 2L, 2L), .Label = c("low", 
    "medium", "high"), class = "factor"), Q4 = c("A little", 
    "Some", "Some", "A great deal", "A lot", "Some")), row.names = c(NA, 
-6L), class = c("tbl_df", "tbl", "data.frame"))
# make column names coherent and simplified
names(df) <- c("Q52_bin", "Q53_bin", "Q57_bin", "response")

df %>% 
  pivot_longer(!response, names_to = "bin_name", values_to = "b") %>% 
  count(response, bin_name, b) %>% 
  ggplot(aes(x=n,y=response)) +
  geom_col(position="stack", stat="identity") +
  scale_fill_discrete()+
  facet_grid(vars(b), vars(bin_name)) + labs(caption = "How much have you thought about climate change before today?", x = "", y = "")

However, what I'd really like is for these bars to be stacked horizontal bars with a single bar inside each facet using colours to indicate the different likert responses. I was thinking I could simply switch to:

  ggplot(aes(x=n,fill=response)) +
  geom_bar(position="fill") +

but the output is incoherent (zillions of narrow bars). Any suggestions on how I can switch this as desired?


Solution

  • Not sure if I understand your question but I would assume this is what you are after.

    Sample code:

     df %>% 
          pivot_longer(!response, names_to = "bin_name", values_to = "b") %>% 
          count(response, bin_name, b) %>% 
          ggplot(aes(x=n,y=b, fill=response)) +
          geom_bar(position="stack", stat="identity") +
          scale_fill_discrete()+
          facet_grid(vars(b), vars(bin_name)) + 
          labs(caption = "How much have you thought about climate change before today?", x = "", y = "")
    

    Plot:

    enter image description here

    And if change

    facet_grid(~b) # b takes values medium and high
    
    
    
      response     bin_name b          n
       <chr>        <chr>    <fct>  <int>
     1 A great deal Q52_bin  medium     1
     2 A great deal Q53_bin  medium     1
     3 A great deal Q57_bin  medium     1
     4 A little     Q52_bin  high       1
     5 A little     Q53_bin  medium     1
     6 A little     Q57_bin  medium     1
     7 A lot        Q52_bin  medium     1
     8 A lot        Q53_bin  medium     1
     9 A lot        Q57_bin  medium     1
    10 Some         Q52_bin  medium     3
    11 Some         Q53_bin  medium     2
    12 Some         Q53_bin  high       1
    13 Some         Q57_bin  medium     3
    

    If you want to ignore the Q52_bin...-s

    enter image description here

    and to make more nicer use a different theme

    library(ggtheme)
    
    theme_gdocs()
    

    enter image description here