How to change axis text after reordering the axis by value in ggplot

Viewed 94

I am trying to make a ggplot where the order of a categorical variable on the y axis is 1) reordered by the value of another variable and then 2) the axis text is swapped for another value where a given level of the new labels could have more than one corresponding value from the original variable. Here's a reproducible example accomplishing the first part:

df <- data.frame(id = rep(letters[1:5], each=10),
                 id_2 = rep(c('group1', 'group2', 'group1', 'group3', 'group4'), each=10),
                 date = rep(seq(0, 9), 5),
                 start_point = rep(rnorm(5, 0, 1), each=10),
                 change_rate = rep(rnorm(5, 0, 1), each=10),
                 variance = rnorm(50, 0, 1))

df$fill_val <- df$start_point + df$date*df$change_rate + df$variance

ggplot(df, aes(x=date, y=reorder(id, fill_val), fill=fill_val)) +
  geom_tile()

This produces:

Example 1

Now, I would like to replace the labels on the y axis with the values found in id_2. Note that you could of course do this manually in this toy example like so:

ggplot(df, aes(x=date, y=reorder(id, fill_val), fill=fill_val)) +
  geom_tile() +
  scale_y_discrete(breaks=c('d', 'b', 'a', 'e', 'c'), 
                   labels=c('group3', 'group2', 'group1', 'group4', 'group1'))

producing:

Example 2

But with the real data, I need to do this repeatedly, and in some plots there may be dozens of values on the y axis, so it can't be a manual fix as above.

2 Answers

This could be achieved via a named vector for the labels. This vector could be constructed using e.g. tibble::deframe:

set.seed(42)

df <- data.frame(id = rep(letters[1:5], each=10),
                 id_2 = rep(c('group1', 'group2', 'group1', 'group3', 'group4'), each=10),
                 date = rep(seq(0, 9), 5),
                 start_point = rep(rnorm(5, 0, 1), each=10),
                 change_rate = rep(rnorm(5, 0, 1), each=10),
                 variance = rnorm(50, 0, 1))

df$fill_val <- df$start_point + df$date*df$change_rate + df$variance

library(ggplot2)
library(tibble)
library(dplyr)

labels <- df %>% 
  select(id, id_2) %>% 
  distinct() %>% 
  tibble::deframe()

ggplot(df, aes(x=date, y=reorder(id, fill_val), fill=fill_val)) +
  geom_tile() +
  scale_y_discrete(labels = labels)

You can also try:

library(ggplot2)
#Data
df <- data.frame(id = rep(letters[1:5], each=10),
                 id_2 = rep(c('group1', 'group2', 'group1', 'group3', 'group4'), each=10),
                 date = rep(seq(0, 9), 5),
                 start_point = rep(rnorm(5, 0, 1), each=10),
                 change_rate = rep(rnorm(5, 0, 1), each=10),
                 variance = rnorm(50, 0, 1))

df$fill_val <- df$start_point + df$date*df$change_rate + df$variance

#Keys
vals <- df[!duplicated(df$id),c('id','id_2')]
#Plot
ggplot(df, aes(x=date, y=reorder(id, fill_val), fill=fill_val)) +
  geom_tile()+
  scale_y_discrete(breaks=vals$id, 
                   labels=vals$id_2)

Output:

enter image description here

Related