Reorder x-axis by y-axis in facet_wrap, ggplot2

51 Views Asked by At

Here is my example:

set.seed(1)
x <- replicate(n = 5, 'left')
y <- replicate(n = 5, 'right')
dir <- c(x,y)
quantity <- sample(seq(1,100), 10)
names <- rep(letters[1:5],2)
tb <- tibble(dir,quantity,names) %>%
  group_by(dir) %>%
  arrange(desc(quantity))

tb %>%
  ggplot(aes(x = fct_inorder(names), quantity)) +
    geom_bar(stat = 'identity', color = 'black') +
  coord_flip() +
  facet_wrap(~dir, scales = "free")

enter image description here

What I would like is to have both the left and right reorder the x-axis by descending order of quantity.

2

There are 2 best solutions below

0
stefan On

To reorder the facets individually you could (have to) use a helper column, i.e. the interaction of your y axis variable and the variable you facet by. Then reorder your data in your desired order (as you already did) and afterwards set the order of the helper column according to the order of the data using fct_inorder. Finally, map the helper column on y and clean up the labels, i.e. remove the part of label corresponding to the facetting variable.

Note: You might also have a look at the tidytext package which provides convenience functions reorder_within and scale_x/y_reordered to achieve the same result using the same approach under the hood.

library(tidyverse)

tb <- tibble(dir, quantity, names) %>%
  arrange(dir, desc(quantity)) |>
  mutate(
    y_ordered = paste(dir, names, sep = "."),
    y_ordered = fct_inorder(y_ordered)
  )

tb %>%
  ggplot(aes(quantity, y_ordered)) +
  geom_col(color = "black") +
  scale_y_discrete(
    # Clean up the axis labels
    labels = \(x) gsub("^.*?\\.", "", x)
  ) +
  facet_wrap(~dir, scales = "free_y")

0
LMc On

You can also use the tidytext package which has functionality specifically for this (reorder_within and scale_*_reordered):

library(ggplot2)
library(tidytext)
library(dplyr)

tb <- tibble(dir,quantity,names) |>
  mutate(grp = reorder_within(name, quantity, within = dir))

tb %>%
  ggplot(aes(x = grp, quantity)) +
  geom_bar(stat = 'identity', color = 'black') +
  coord_flip() +
  scale_x_reordered(limits = rev) + 
  facet_wrap(~dir, scales = "free_y")

enter image description here