How to order data by value within ggplot facets

We can use

(1) reorder_within() function to reorder term within tissue facets.

library(tidyverse)
library(forcats)

tdat <- tdat %>% 
  mutate(term = factor(term),
         tissue = factor(tissue, levels = c("tissue-C", "tissue-A", "tissue-D", "tissue-B"), 
                         ordered = TRUE))

reorder_within <- function(x, by, within, fun = mean, sep = "___", ...) {
  new_x <- paste(x, within, sep = sep)
  stats::reorder(new_x, by, FUN = fun)
}

scale_x_reordered <- function(..., sep = "___") {
  reg <- paste0(sep, ".+$")
  ggplot2::scale_x_discrete(labels = function(x) gsub(reg, "", x), ...)
}

ggplot(tdat, aes(reorder_within(term, score, tissue), score)) +
  geom_segment(aes(xend = reorder_within(term, score, tissue), yend = 0), 
               colour = "grey50") +
  geom_point(size = 3, aes(colour = tissue)) + 
  scale_x_reordered() +
  facet_grid(tissue ~ ., scales = "free", space = "free") +
  coord_flip() +
  scale_colour_brewer(palette = "Dark2") +
  theme_bw() +
  theme(panel.grid.major.y = element_blank()) + 
  theme(legend.position = "bottom")

Or (2) similar idea

### https://trinkerrstuff.wordpress.com/2016/12/23/ordering-categories-within-ggplot2-facets/
tdat %>% 
  mutate(term = reorder(term, score)) %>%
  group_by(tissue, term) %>% 
  arrange(desc(score)) %>% 
  ungroup() %>% 
  mutate(term = factor(paste(term, tissue, sep = "__"), 
                       levels = rev(paste(term, tissue, sep = "__")))) %>%
    ggplot(aes(term, score)) +
        geom_segment(aes(xend = term, yend = 0), 
                   colour = "grey50") +
        geom_point(size = 3, aes(colour = tissue)) + 
        facet_grid(tissue ~., scales = "free", space="free") +
        scale_x_discrete(labels = function(x) gsub("__.+$", "", x)) +
        coord_flip() +
        scale_colour_brewer(palette = "Dark2") +
        theme_bw() +
        theme(panel.grid.major.y = element_blank()) + 
        theme(legend.position = "bottom",
              axis.ticks.y = element_blank())

Or (3) orders the entire data frame, and also orders the categories (tissue) within each facet group!

### https://drsimonj.svbtle.com/ordering-categories-within-ggplot2-facets
# 
tdat2 <- tdat %>% 
  # 1. Remove grouping
  ungroup() %>% 
  # 2. Arrange by
  #   i.  facet group (tissue)
  #   ii. value (score)
  arrange(tissue, score) %>%
  # 3. Add order column of row numbers
  mutate(order = row_number())
tdat2

#> # A tibble: 40 x 4
#>    term                                                tissue  score order
#>    <fct>                                               <ord>   <dbl> <int>
#>  1 Hepatic Fibrosis / Hepatic Stellate Cell Activation tissue~  1.31     1
#>  2 Sumoylation Pathway                                 tissue~  1.34     2
#>  3 Factors Promoting Cardiogenesis in Vertebrates      tissue~  1.4      3
#>  4 Role of Oct4 in Mammalian Embryonic Stem Cell Plur~ tissue~  1.56     4
#>  5 Aryl Hydrocarbon Receptor Signaling                 tissue~  1.86     5
#>  6 Hereditary Breast Cancer Signaling                  tissue~  2.23     6
#>  7 ATM Signaling                                       tissue~  2.55     7
#>  8 GADD45 Signaling                                    tissue~  2.6      8
#>  9 Granzyme B Signaling                                tissue~  2.91     9
#> 10 Role of BRCA1 in DNA Damage Response                tissue~  5.61    10
#> # ... with 30 more rows

ggplot(tdat2, aes(order, score)) +
  geom_segment(aes(xend = order, yend = 0), 
               colour = "grey50") +
  geom_point(size = 3, aes(colour = tissue)) +
  facet_grid(tissue ~ ., scales = "free", space = "free") +
  coord_flip() +
  scale_colour_brewer(palette = "Dark2") +
  theme_bw() +
  theme(panel.grid.major.y = element_blank()) + 
  theme(legend.position = "bottom")

# To finish we need to replace the numeric values on each x-axis 
# with the appropriate labels
ggplot(tdat2, aes(order, score)) +
  geom_segment(aes(xend = order, yend = 0), 
               colour = "grey50") +
  geom_point(size = 3, aes(colour = tissue)) + 
  scale_x_continuous(
    breaks = tdat2$order,
    labels = tdat2$term) +
  # scale_y_continuous(expand = c(0, 0)) +
  facet_grid(tissue ~ ., scales = "free", space = "free") +
  coord_flip() +
  scale_colour_brewer(palette = "Dark2") +
  theme_bw() +
  theme(panel.grid.major.y = element_blank()) + 
  theme(legend.position = "bottom",
        axis.ticks.y = element_blank())

Leave a Comment