rggplot2

Reorder factor levels to display correctly in facet wrapped bar chart


I am trying to reorder the levels in my variable "response" so they show in the correct order on my bar charts. The order of levels should be "yes", "no" and "less than one year", "one year", "greater than one year". However, when I try to reorder them using the factor() function some of my variable levels are replaced with NA.

enter image description here

Here is my code:

library(tidyverse)
library(scales)

percent <- c(0.20, .56, .36, .36, .78, .64, 0.20)
response <- c(rep(c("yes", "no"), 2), c("less than one year", "one year", "greater than one year"))
question <- c(rep("dogs",2), rep("cats",2), rep("years at home",3)) 

survey <- data.frame(percent, response, question) %>% 
  mutate(response = str_wrap(response, width = 8)) %>% 
  mutate(response = factor(response, levels = c("yes", "no", "less than one year", "one year", "greater than one year")))

ggplot(survey, aes(x=response, y=percent)) +
  geom_bar(stat = "identity", position = "dodge") +
  geom_text(aes(label = scales::percent(percent),
                y= percent), position = position_dodge(width = 1), vjust = -.5) +
  scale_y_continuous(breaks = seq(0, 1.1,0.2),
                     limits = c(0,1.1),
                     labels=percent_format(accuracy = 1),
                     expand = c(0,0)) +
  labs(title = "",
       x = "",
       y = "Percentage") +
  facet_wrap(~question, scales = "free") +
  theme_bw() +
  theme(plot.title = element_text(family = "sans", 
                                  face = "bold", 
                                  hjust = 0.5, 
                                  size = 14, 
                                  margin = margin(0,0,10,0)),
        axis.text = element_text(family = "sans",
                                 size = 11),
        axis.text.y = element_text(margin = margin(0,0,0,5),
                                   size = 12),
        axis.text.x = element_text(size = 12,
                                   angle = 0,
                                   margin = margin(5,0,0,0)),
        axis.title.x = element_text(family = "sans",
                                    size = 14,
                                    margin = margin(10,0,0,0)),
        axis.title.y = element_text(family = "sans",
                                    size = 14),
        plot.caption = element_text(hjust = 0.5, vjust = -1.0, size = 12, 
                                    margin = margin(4,0,0,0)),
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        strip.text = element_text(size = 11, face = "bold"))

Solution

  • The values in your response variable need to be called as "less\nthan one\nyear" and "greater\nthan one\nyear" because they include new line ("\n") characters. This should solve the issue!

    survey <- data.frame(percent, response, question) %>% 
      mutate(response = str_wrap(response, width = 8)) %>% 
      mutate(response = factor(response, levels = c("no", "yes", "less\nthan one\nyear", "one year", "greater\nthan one\nyear")))
    

    If this still didn't provide the correct order, you could add as.ordered = T as an option in your factor function, but the above example seems to work fine.