rdataframeggplot2likert

Combine likert chart and bar plot ordered by the same order in R using ggplot2


I have a data frame in R produced randomly as you can see in the code section below called df. I want to create two plots using ggplot.The one will be likert chart (horizontal chart) and the other bar chart. but i want to be sorted with the same order. the y axis in the v1 chart must be the same with the v2 y axis chart. In the picture below the y axis has (from top to bottom ) B,A,D,C categories and the v2 has D,C,B,A. I want the categories in the y axis to be matched. How can i do this in R ?


library(tibble)

var_levels <- c("A", "B", "C", "D")
likert_levels <- c(
  "Strongly disagree",
  "Disagree",
  "Neither agree nor disagree",
  "Agree",
  "Strongly agree"
)


set.seed(42)
df <- tibble(
  var = sample(var_levels, 50, replace = TRUE),  # Random values from A to D
  val = sample(likert_levels, 50, replace = TRUE)  # Random values from Likert levels
)


df2=df%>%
  mutate(across(everything(), as.factor))%>%
  group_by(var)%>%
  mutate(row = row_number()) %>%
  pivot_wider(names_from = var,   # The values in 'var' will become new column names
              values_from = val)%>%
  select(-row)

v1 = ggstats::gglikert(df2)+
  aes(y = reorder(.question,
                  ifelse(
                    .answer %in% c("Strongly disagree", "Disagree"),
                    1, 0),FUN = sum),decreasing=TRUE)



df_total = df%>%
  count(var,val) %>% 
  group_by(var) %>% 
  mutate(pct = round(prop.table(n) * 100, 1)) %>% 
  select(-n) %>% 
  filter(!is.na(val)) %>% 
  pivot_wider(names_from = val, values_from = pct)
colnames(df_total) = c("var",likert_levels)
df_total  = df_total%>%
  mutate(order = `Strongly disagree` + Disagree )%>%
  arrange(desc(order))

v2 = df%>%
  mutate(across(everything(), as.factor))%>%
  group_by(var)%>%
  summarise(count=n())%>%
  ggplot(., aes(x = var, y = count)) +
  geom_bar(stat = "identity", fill = "lightgrey")+
  coord_flip()


ggarrange(v1,v2,widths = c(6,2))


enter image description here


Solution

  • You have to use the same order for the factor mapped on y in the second plot, e.g. use the same reorder before computing the counts.

    Note: I switched x and y to get rid of coord_flip.

    library(tidyverse)
    library(ggstats)
    library(ggpubr)
    
    v2 <- df %>%
      mutate(
        var = reorder(var,
          ifelse(
            val %in% c("Strongly disagree", "Disagree"),
            1, 0
          ),
          FUN = sum
        )
      ) |>
      count(var, name = "count") %>%
      ggplot(., aes(y = var, x = count)) +
      geom_bar(stat = "identity", fill = "lightgrey")
    
    ggarrange(v1, v2, widths = c(6, 2))