Search code examples
rggplot2groupinglikert

Order ascending/descending in likert() with grouping


This is my dataframe

library(likert)

# Create dataframe
group <-    c("A","B","C","C","B","A","B","C","A","B","A","C","B","B","C","A","B","B","A","C","B","B","A","A")
question1<- c(1,2,3,2,2,3,1,3,1,2,3,1,3,2,3,1,2,3,3,1,2,3,2,1)
question2<- c(1,2,3,2,1,1,1,3,3,2,1,3,2,2,3,1,2,3,1,2,3,1,2,1)
question3<- c(1,1,1,2,2,2,3,3,3,2,2,3,1,3,2,2,3,2,3,1,2,3,1,2)
question4<- c(3,3,3,2,1,2,3,3,2,1,2,2,3,1,3,2,2,1,2,3,3,2,1,2)
my_df <-data.frame(group,question1,question2,question3,question4)

# Add label 
my_df[, 2:5] <- lapply(my_df[, 2:5], factor,
                                      levels=c(1, 2, 3), 
                                      labels = c("Competent", "Average", "Imcompetent")) 
my_df <- as.data.frame(my_df)

# Draw graph using likert()
graph <- plot(likert(my_df[, 2:5], grouping=my_df[, 1]), wrap = 60, text.size=4, col=c("#C70039", "#E0DCD8", "#DAF7A6")) +
  guides(fill=guide_legend("")) +# plot graph
  theme(legend.text =element_text(color="black",size=12), axis.text=element_text(color="black",size=12), strip.text=element_text(size=15))
graph

And the result looks like this enter image description here

I want to reorder the groups within each question block in ascending/descending order basing on the share of competent answer. For example, groups in "question1" block will be ordered as A, C, B; and "question3" block will be C, A, B.

Thank you in advance!

I have listed what I tried above


Solution

  • I don't think ggplot2 is going to support this natively, so we can generate each question individually and combine them with the patchwork package.

    We'll remove the x-axis name/labels/ticks for all but the bottom question, and we will combine the legends into one at the bottom.

    In order to control the order of the groups on the y-axis, as is always the case when a ggplot2 question asks "how to control the order": factors (and their levels).

    plots <- lapply(2:5, function(i) {
      lik <- likert(my_df[, i, drop=FALSE], grouping=my_df[, 1])
      lik$results$Group <-
        factor(lik$results$Group, levels = lik$results$Group[ order(lik$results$Competent) ])
      p <- plot(lik, wrap=60, text.size=4, col=c("#C70039", "#E0DCD8", "#DAF7A6")) +
        guides(fill = guide_legend("")) +# plot graph
        theme(
          legend.text = element_text(color="black", size=12),
          axis.text = element_text(color="black", size=12),
          strip.text = element_text(size=15))
      if (i < 5) {
        p <- p +
          theme(axis.title.x=element_blank(),
                axis.text.x=element_blank(),
                axis.ticks.x=element_blank())
      }
      p
    })
    
    library(patchwork)
    Reduce(`/`, plots) + plot_layout(guides = "collect") &
      theme(legend.position = "bottom")
    

    ggplot combined single-facets with y-axis groups individually ordered