Search code examples
rggplot2plottidytext

Customizing axes in faceted ggplot with tidytext and reorder_within


I have the following code to make a complicated plot with the help of reorder_within from tidytext and, apparently, brand-new features in faceting in ggplot. The snippet below includes the real data and all the other formatting for the plot, in case one of those is causing the issue I'm encountering.

library(ggplot2)
library(tidyverse)
library(tidytext)

# create dataframe 
feature <- c("Centroid", "Centroid", "Centroid", "Centroid", "Centroid", 
"Centroid", "Centroid", "Centroid", "Centroid", "Centroid", "Centroid", 
"Centroid", "Centroid", "Centroid", "Centroid", "Centroid", "Centroid", 
"Centroid", "Centroid", "Centroid", "Centroid", "Centroid", "Centroid", 
"Centroid", "Cold Edge", "Cold Edge", "Cold Edge", "Cold Edge", 
"Cold Edge", "Cold Edge", "Cold Edge", "Cold Edge", "Cold Edge", 
"Cold Edge", "Cold Edge", "Cold Edge", "Cold Edge", "Cold Edge", 
"Cold Edge", "Cold Edge", "Cold Edge", "Cold Edge", "Cold Edge", 
"Cold Edge", "Cold Edge", "Cold Edge", "Cold Edge", "Cold Edge", 
"Warm Edge", "Warm Edge", "Warm Edge", "Warm Edge", "Warm Edge", 
"Warm Edge", "Warm Edge", "Warm Edge", "Warm Edge", "Warm Edge", 
"Warm Edge", "Warm Edge", "Warm Edge", "Warm Edge", "Warm Edge", 
"Warm Edge", "Warm Edge", "Warm Edge", "Warm Edge", "Warm Edge", 
"Warm Edge", "Warm Edge", "Warm Edge", "Warm Edge")
id <- c("GAM", "GAM", "Persistence", "Persistence", "v12", "v12", "v14", 
"v14", "v25", "v25", "v37", "v37", "v41", "v41", "v42", "v42", 
"v43", "v43", "v48", "v48", "v58", "v58", "v60", "v60", "GAM", 
"GAM", "Persistence", "Persistence", "v12", "v12", "v14", "v14", 
"v25", "v25", "v37", "v37", "v41", "v41", "v42", "v42", "v43", 
"v43", "v48", "v48", "v58", "v58", "v60", "v60", "GAM", "GAM", 
"Persistence", "Persistence", "v12", "v12", "v14", "v14", "v25", 
"v25", "v37", "v37", "v41", "v41", "v42", "v42", "v43", "v43", 
"v48", "v48", "v58", "v58", "v60", "v60")
metric <- c("RMSE", "Bias", "RMSE", "Bias", "RMSE", "Bias", "RMSE", "Bias", 
"RMSE", "Bias", "RMSE", "Bias", "RMSE", "Bias", "RMSE", "Bias", 
"RMSE", "Bias", "RMSE", "Bias", "RMSE", "Bias", "RMSE", "Bias", 
"RMSE", "Bias", "RMSE", "Bias", "RMSE", "Bias", "RMSE", "Bias", 
"RMSE", "Bias", "RMSE", "Bias", "RMSE", "Bias", "RMSE", "Bias", 
"RMSE", "Bias", "RMSE", "Bias", "RMSE", "Bias", "RMSE", "Bias", 
"RMSE", "Bias", "RMSE", "Bias", "RMSE", "Bias", "RMSE", "Bias", 
"RMSE", "Bias", "RMSE", "Bias", "RMSE", "Bias", "RMSE", "Bias", 
"RMSE", "Bias", "RMSE", "Bias", "RMSE", "Bias", "RMSE", "Bias"
)
value <- c(0.801070122304678, -0.534741093961753, 0.467898529138353, 0.253097435554975, 
0.654310485581312, -0.522202007556253, 0.653639262514227, -0.520142423389587, 
0.504373623210596, -0.298788571167364, 0.449641913849529, -0.220897132278475, 
0.674179658706584, -0.529209185056253, 0.560624534248649, -0.187414410056253, 
0.445722378396105, -0.199835395611809, 0.654990963488094, -0.521727642556253, 
0.566365429195672, -0.160961203389586, 0.537288435994822, -0.35171970922292, 
1.5439548201309, 1.48899798183722, 0.298219645613402, 0.10580599267638, 
0.305448117459807, -0.11412270283058, 0.306195919644046, -0.114706875414081, 
0.428209249400843, -0.320960558239865, 0.29390890871898, -0.0376057753447458, 
0.469447200492398, 0.302370846004949, 0.760678565420607, 0.598754260027916, 
0.34771925417122, -0.197943210268751, 0.322115144705871, -0.15602600887745, 
0.841655175267095, 0.646341561152582, 0.355579385009809, 0.172469737398153, 
1.12636471666085, -0.968328329322702, 0.880001424291427, 0.739574347117147, 
0.730944154231202, -0.54421969449278, 0.728438716816235, -0.539437580735593, 
0.454530326111766, -0.0616912965605267, 0.491473526205237, -0.0858113233294449, 
0.92734194845549, -0.796362896903439, 0.656115208573224, -0.301658495784424, 
0.44626429226838, -0.0284186717887785, 0.686891459111237, -0.479718985851968, 
0.656437690895435, -0.288587484139443, 0.711464224386588, -0.524004379483176
)

# bind into data frame 
dat <- data.frame(cbind(feature, id, metric, value))
dat$value <- as.numeric(dat$value)

# make plot
dat %>%
         mutate(
           metric = factor(metric, levels = c("RMSE","Bias")),
           id = reorder_within(id, value, list(metric, feature))) %>%  
  ggplot( )+
  geom_point(aes(id, y=value)) + 
  geom_hline(yintercept=0) + 
  coord_flip() + 
  scale_x_reordered() +
  scale_y_continuous(expand = c(0,0)) +
  theme_bw() + 
  facet_grid(feature ~ metric, scales="free", axes="all_y", axis.labels = "all_y") +
  theme(axis.title.x = element_blank(), 
        axis.title.y = element_blank()) +
  NULL

The problem is easiest to explain when looking at the plot: each y-axis has a custom order, but (I think) because the orders aren't the same between facets, ggplot is printing the same id multiple times on each y-axis. This creates a lot of "empty" rows and makes the plot ugly and hard to read. What I want is for each value of id to appear once on each y-axis, but ordered by the value on the x-axis, which will lead to a different order for each facet. This happens automagically in the reorder_within example I linked above, so I'm not sure what I'm doing wrong here. I was hoping adding axes="all_y", axis.labels = "all_y" to facet_grid would resolve the issue but they did not.

enter image description here


Solution

  • The issue is that you using facet_grid. And TBMK there is no way to achieve your desired result using facet_grid. Instead I would suggest to switch to facet_wrap or ggh4x::facet_nested_wrap as I do below:

    library(tidyverse)
    library(tidytext)
    
    dat %>%
      mutate(
        metric = factor(metric, levels = c("RMSE", "Bias")),
        id = reorder_within(id, value, list(metric, feature))
      ) %>%
      ggplot() +
      geom_point(aes(value, id)) +
      geom_vline(xintercept = 0) +
      scale_y_reordered() +
      scale_x_continuous(expand = c(0, 0)) +
      theme_bw() +
      ggh4x::facet_nested_wrap(~feature+metric, scales = "free_y", ncol = 2) +
      theme(
        axis.title = element_blank()
      )