Home > Blockchain >  Stacked percentage bar chart went wrong in ggplot
Stacked percentage bar chart went wrong in ggplot

Time:09-14

I wanted to create a stacked percentage bar chart, but something went wrong. I can create a normal stacked bar chart, but as soon as I replace the "stacked" with "fill" under position, it gives me this incorrect bar chart:

enter image description here

I used this code:

ggplot(dataset, aes(fill = family_role_recoded, x=country, y=family_role_recoded)) geom_bar(position="fill", stat="identity")

Here a reproducible example:

structure(list(country = c("Lebanon", "Algeria", "Iraq", "Jordan", 
"Morocco", "Lebanon", "Lebanon", "Lebanon", "Lebanon", "Lebanon", 
"Lebanon", "Lebanon", "Lebanon", "Lebanon", "Lebanon", "Lebanon", 
"Lebanon", "Lebanon", "Lebanon", "Lebanon", "Lebanon", "Lebanon", 
"Lebanon", "Lebanon", "Lebanon"), urban_rural = structure(c(2L, 
2L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 1L, 2L, 2L, 2L, 1L, 2L, 2L), levels = c("Rural", "Urban", 
"Refugee camp"), class = "factor"), age = c(41L, 36L, 33L, 26L, 
28L, 33L, 31L, 45L, 70L, 18L, 23L, 20L, 24L, 44L, 38L, 39L, 23L, 
45L, 26L, 54L, 26L, 22L, 33L, 62L, 18L), education = c("Preparatory/Basic", 
"Preparatory/Basic", "Secondary", "Elementary", "Mid-level diploma/professional or technical", 
"Secondary", "Elementary", "Elementary", "Elementary", "Secondary", 
"BA", "Secondary", "BA", "Preparatory/Basic", "Elementary", "BA", 
"Secondary", "BA", "Preparatory/Basic", "Secondary", "Secondary", 
"Preparatory/Basic", "Preparatory/Basic", "Preparatory/Basic", 
"Secondary"), family_role = structure(c(1L, 2L, 2L, 1L, 2L, 2L, 
2L, 3L, 2L, 3L, 2L, 3L, 1L, 3L, 2L, 3L, 3L, 2L, 2L, 4L, 2L, 2L, 
3L, 1L, 3L), levels = c("I strongly agree", "I agree", "I disagree", 
"I strongly disagree", "Don't know", "Refused to answer"), class = "factor"), 
    religious = structure(c(2L, 1L, 2L, 2L, 3L, 2L, 2L, 3L, 1L, 
    3L, 3L, 1L, 3L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
    3L), levels = c("Religious", "Somewhat religious", "Not religious"
    ), class = "factor"), gender = c("Male", "Female", "Female", 
    "Male", "Male", "Male", "Male", "Male", "Male", "Male", "Female", 
    "Male", "Male", "Female", "Male", "Female", "Female", "Male", 
    "Female", "Female", "Male", "Male", "Male", "Female", "Male"
    ), education_cat = structure(c(2L, 2L, 3L, 2L, 3L, 3L, 2L, 
    2L, 2L, 3L, 4L, 3L, 4L, 2L, 2L, 4L, 3L, 4L, 2L, 3L, 3L, 2L, 
    2L, 2L, 3L), levels = c("No formal education", "Basic education", 
    "Secondary education", "Higher education"), class = "factor"), 
    family_role_recoded = structure(c(2L, 2L, 2L, 2L, 2L, 2L, 
    2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 1L, 2L, 2L, 1L, 2L, 
    2L, 1L, 2L, 1L), levels = c("Disagree/strongly disagree", 
    "Agree/strongly agree", "Don't know"), class = "factor")), row.names = c(NA, 
25L), class = "data.frame")

I appreciate any advice!

Best regards

CodePudding user response:

My suggestion would be as follows:

library(ggplot2)

library(scales)

df|> ggplot(aes(x=country, fill = family_role_recoded)) geom_bar(position = "fill") scale_y_continuous(labels=scales::percent)

CodePudding user response:

I would suggest something like this:


    df_agg <- df %>% 
      group_by(country, family_role_recoded) %>% 
      summarise(count = n()) %>% 
      ungroup() %>% 
      group_by(country) %>% 
      mutate(total = sum(count)) %>% 
      ungroup() %>% 
      mutate(percentage = count/total)

    levels <- df_agg$country[df_agg$family_role_recoded=="Agree/strongly agree"][rev(order(df_agg$percentage[df_agg$family_role_recoded=="Agree/strongly agree"]))]
    df_agg$country <- factor(df_agg$country, levels = levels)
    
    g1 <- ggplot(df_agg, aes(fill=family_role_recoded, x=country, y = percentage ))   
      geom_bar(position="fill", stat="identity")

  • Related