Lets say, in R, I have a data frame letters, numbers and animals and I want to examine the relationship between all three graphically. I could do something like.
library(dplyr)
library(ggplot2)
library(gridExtra)
set.seed(33)
my_df <- data.frame(
letters = c(letters[1:10], letters[6:15], letters[11:20]),
animals = c(rep('sheep', 10), rep('cow', 10), rep('horse', 10)),
numbers = rnorm(1:30)
)
ggplot(my_df, aes(x = letters, y = numbers)) + geom_point() +
facet_wrap(~animals, ncol = 1, scales = 'free_x')
I'd get something that looks like.
However, I want the order of the x axis to be dependent on the order of the y-axis. This is easy enough to do without facets, as per this example.
I can even make an ordered figure for each animal and then bind them together with grid.arrange as in this example
my_df_shp <- my_df %>% filter(animals == 'sheep')
my_df_cow <- my_df %>% filter(animals == 'cow')
my_df_horse <- my_df %>% filter(animals == 'horse')
my_df_shp1 <- my_df_shp %>% mutate(letters = reorder(letters, numbers))
my_df_cow1 <- my_df_cow %>% mutate(letters = reorder(letters, numbers))
my_df_horse1 <- my_df_horse %>% mutate(letters = reorder(letters, numbers))
p_shp <- ggplot(my_df_shp1, aes(x = letters, y = numbers)) + geom_point()
p_cow <- ggplot(my_df_cow1, aes(x = letters, y = numbers)) + geom_point()
p_horse <- ggplot(my_df_horse1, aes(x = letters, y = numbers)) + geom_point()
grid.arrange(p_shp, p_cow, p_horse, ncol = 1)
I don't particularly like this solution though, because it isn't easily generalizable to cases where there are a lot of facets.
I'd rather do something like
ggplot(my_df, aes(x = y_ordered_by_facet(letters, by = numbers), y = numbers)) + geom_point() +
facet_wrap(~animals, ncol = 1, scales = 'free_x')
Where y_ordered is some function that cleverly orders the letters factor to be in the same order as the numbers.
Something that gets close to this, but doesn't quite seem to work is
ggplot(my_df, aes(x = reorder(letters, numbers), y = numbers)) +
geom_point() + facet_wrap(~animals, ncol = 1, scales = 'free_x')
That doesn't quite work because the order ends up taking effect before, rather than after the facet wrapping and thus putting the labels in not quite the right order for each panel.
Any clever ideas?
See Question&Answers more detail:
os