Search code examples
rggplot2facet-wrap

How to order frequency counts of categorical variables by group facet_wrap in ggplot2?


I am trying to create bar graphs of categorical data ordered by frequency within groups. For example, using the diamonds dataset, I would like bar graphs ordered by counts/ frequency of "clarity" values grouped by "cut."

data(diamonds)
library(tidyverse)

diamonds$cut <- as.character(diamonds$cut)
diamonds$clarity <- as.character(diamonds$clarity)

diamonds %>% 
  group_by(cut) %>% 
  count(clarity, order = FALSE) %>% 
  mutate(clarity = as.factor(reorder(clarity, n))) %>% 
  ggplot(aes(n, clarity, fill = cut)) +
  geom_col(show.legend = FALSE) +
  facet_wrap(~ cut, ncol = 2, scales = "free") +
  labs(x = "count", y = NULL) +
  theme_bw()

This produces the following graph: enter image description here

It is very close to what I want, but the only graph actually ordered by clarity frequency is the first, "Fair." How can I make the all the bar graphs ordered by clarity frequency?

Thanks in advance.


Solution

  • One option would be to use reorder_within and scale_y_reorderd from the tidytext package:

    library(ggplot2)
    library(dplyr, warn = FALSE)
    library(tidytext)
    
    diamonds$cut <- as.character(diamonds$cut)
    diamonds$clarity <- as.character(diamonds$clarity)
    
    diamonds %>%
      group_by(cut) %>%
      count(clarity, order = FALSE) %>%
      mutate(clarity = tidytext::reorder_within(clarity, n, cut)) %>%
      ggplot(aes(n, clarity, fill = cut)) +
      geom_col(show.legend = FALSE) +
      tidytext::scale_y_reordered() +
      facet_wrap(~cut, ncol = 2, scales = "free") +
      labs(x = "count", y = NULL) +
      theme_bw()