rdataframeggplot2

Horizontally match levels of Likert chart based on another bar plot in R


i have a data frame in r called df similar to these question found here:

set.seed(123)
likert_levels <- c(
  "1" = "Very  Dissatisfied",
  "2" = "Dissatisfied",
  "3" = "Neutral",
  "4" = "Satisfied",
  "5" = "Very  Satisfied")
df = data.frame(
  year = sample(c(2023, 2022, 2020, 2018), 50, replace = TRUE),
  A = sample(likert_levels, 50, replace = TRUE),
  B = sample(likert_levels, 50, replace = TRUE),
  C = sample(likert_levels, 50, replace = TRUE))%>%
  mutate(across(everything(),as.factor))%>%
  as_tibble()%>%
  mutate(across(-year, ~ factor(.x, levels = likert_levels)))
df

the likert chart i can do it like this :

mutate(df, id=row_number()) |>
  pivot_longer(-c(id, year), names_to="group") |>
  pivot_wider(names_from=year) |>
  gglikert(c(`2023`, `2022`, `2020`, `2018`), 
         facet_rows=vars(group))

but in this setup i want to sort the likert plot based on the descending sorting of the bar plot . I.e i want to sort first the bar plot in a descending order and then based on this sorting to be sorted accordingly the likert plot . How can i do it in R ?


Solution

  • Here is one potential approach:

    library(tidyverse)
    library(ggstats)
    library(patchwork)
    
    set.seed(123)
    likert_levels <- c(
      "1" = "Very  Dissatisfied",
      "2" = "Dissatisfied",
      "3" = "Neutral",
      "4" = "Satisfied",
      "5" = "Very  Satisfied")
    df = data.frame(
      year = sample(c(2023, 2022, 2020, 2018), 50, replace = TRUE),
      A = sample(likert_levels, 50, replace = TRUE),
      B = sample(likert_levels, 50, replace = TRUE),
      C = sample(likert_levels, 50, replace = TRUE))%>%
      mutate(across(everything(),as.factor))%>%
      as_tibble()%>%
      mutate(across(-year, ~ factor(.x, levels = likert_levels)))
    
    # starting plot
    likert <- df |>
      mutate(id = row_number()) |>
      pivot_longer(-c(id, year), names_to="group") |>
      pivot_wider(names_from=year) |>
      gglikert(c(`2023`, `2022`, `2020`, `2018`), 
               facet_rows=vars(group))
    
    # get the order of years according to n
    df2 <- df |>
      mutate(id = row_number()) |>
      pivot_longer(-c(id, year), names_to = "group") |>
      count(group, year) %>%
      arrange(n) %>%
      select(year) %>%
      distinct()
    
    # change the order of years (.question) in the likert dataframe
    likert$data <- likert$data |>
      mutate(.question = factor(.question, levels = df2$year))
    
    # create the barplot
    bar <- df |>
      mutate(id = row_number()) |>
      pivot_longer(-c(id, year), names_to = "group") |>
      count(group, year) |>
      ggplot(aes(x = n, y = fct_reorder(year, n))) +
      geom_col() +
      geom_label(aes(label = n),
                 color = "white", hjust = 1,
                 fill = NA, label.size = 0) +
      facet_wrap(~group, ncol = 1, strip.position = "right") +
      labs(y = NULL) +
      likert$theme
    
    # plot them side by side
    likert + bar + plot_layout(widths = c(0.8, 0.2), guides = "collect") &
      theme(legend.position = "bottom")
    

    likert patchwork

    Created on 2024-12-13 with reprex v2.1.0

    If this isn't your desired outcome, please edit your question and explain exactly what you want your final plot to look like.