Home > Software design >  ggplot stacked bar chart: how can I display percentages on geom_text(aes(label = x) without making b
ggplot stacked bar chart: how can I display percentages on geom_text(aes(label = x) without making b

Time:03-11

With the help of some stars on Stackoverflow, I've got a plot working like a charm. Here's the code:

# ingest some sample data
structure(list(Q52_bin = structure(c(3L, 2L, 2L, 2L, 2L, 2L, 
2L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("low", "medium", 
"high"), class = "factor"), Q53_bin = structure(c(2L, 3L, 2L, 
2L, 2L, 2L, 2L, 3L, 2L, 3L, 2L, 1L, 2L, 2L, 1L), .Label = c("low", 
"medium", "high"), class = "factor"), Q57_bin = structure(c(2L, 
2L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 3L, 2L, 2L, 2L, 2L), .Label = c("low", 
"medium", "high"), class = "factor"), Q4 = c(2, 3, 3, 5, 4, 3, 
4, 5, 2, 4, 2, 3, 5, 4, 3)), row.names = c(NA, -15L), class = c("tbl_df", 
"tbl", "data.frame"))

names(df) <- c("Q52_bin", "Q53_bin", "Q57_bin", "response")
facet_names <- c(`Q52_bin` = "Spirituality", `Q53_bin` = "Politics L/R", `Q57_bin` = "Religiosity", `low`="low", `medium`="medium", `high`="high")
facet_labeller <- function(variable,value){return(facet_names[value])}
q4_levels = c("Not at all", "A little", "Some", "A lot", "A great deal")
df$response <- factor(df$response, ordered = TRUE, levels = c("5", "4", "3", "2", "1"))
df$response <- fct_recode(df$response, "Not at all" = "1", "A little" = "2", "Some" = "3", "A lot" = "4", "A great deal" = "5")

df %>% 
  pivot_longer(!response, names_to = "bin_name", values_to = "b") %>% 
  count(response, bin_name, b) %>%
  ggplot(aes(x = n, y = "", fill = response))  
  geom_col(position="fill", aes(fill=response))  
  ### Problem line is below
  # geom_text(aes(label = n), position = position_stack(vjust = 0.5), size=2)  
  scale_fill_brewer(palette="YlOrBr")  
  scale_x_continuous(labels = scales::percent_format())  
  facet_grid(vars(b), vars(bin_name), labeller=as_labeller(facet_names))   
  labs(caption = "How much have you thought about climate change before today?", x = "", y = "")   
  guides(fill = guide_legend(title = NULL))

There are two problems here: first, I've not been able to find a good way to display percentages on the bars without using dplyr() to add new columns to the dataframe and this seems overly complicated (especially in light of the faceting I'm doing here). The second problem, is that the display of text makes the bars on the chart vanish!

CodePudding user response:

I've adjusted the way I manipulate df from the previous question

df %>% 
  pivot_longer(!response, names_to = "bin_name", values_to = "b") %>% 
  count(response, bin_name, b) %>% 
  group_by(bin_name,b) %>%
  mutate(perc=paste0(round(n*100/sum(n),1),"%")) %>% 
  ggplot(aes(x = n, y = "", fill = response))  
  geom_col(position=position_fill(), aes(fill=response))  
  geom_text(aes(label = perc), position = position_fill(vjust=.5), size=2)  
  scale_fill_brewer(palette="YlOrBr")  
  scale_x_continuous(labels = scales::percent_format())  
  facet_grid(vars(b), vars(bin_name), labeller=as_labeller(facet_names))   
  labs(caption = "How much have you thought about climate change before today?", x = "", y = "")   
  guides(fill = guide_legend(title = NULL))

likert

CodePudding user response:

You are using position_fill for the bars, so you need to use this for the text too:

df %>% 
  pivot_longer(!response, names_to = "bin_name", values_to = "b") %>% 
  count(response, bin_name, b) %>%
  group_by(bin_name, b) %>%
  summarize(label = scales::percent(n / sum(n)), response, n) %>%
  ggplot(aes(x = n, y = "", fill = response))  
  geom_col(position="fill", aes(fill=response))  
  geom_text(aes(label = label), 
            position = position_fill(vjust = 0.5), size = 3)  
  scale_fill_brewer(palette="YlOrBr")  
  scale_x_continuous(labels = scales::percent_format())  
  facet_grid(vars(b), vars(bin_name), labeller=as_labeller(facet_names))   
  labs(caption = "How much have you thought about climate change before today?", 
       x = "", y = "")   
  guides(fill = guide_legend(title = NULL))

enter image description here

Nice plot, by the way!

  • Related