简体   繁体   English

按 y 轴值在 ggplot 的每个方面对因子进行排序

[英]Ordering factors in each facet of ggplot by y-axis value

Lets say, in R, I have a data frame letters, numbers and animals and I want to examine the relationship between all three graphically.比方说,在 R 中,我有一个数据框字母、数字和动物,我想以图形方式检查这三者之间的关系。 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.但是,我希望 x 轴的顺序取决于 y 轴的顺序。 This is easy enough to do without facets, as per this example .根据这个例子,这很容易在没有 facet 的情况下完成。 I can even make an ordered figure for each animal and then bind them together with grid.arrange as in this example我什至可以为每只动物制作一个有序的图形,然后用 grid.arrange 将它们绑定在一起,如本例所示

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')我宁愿做类似 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.其中 y_ordered 是一些函数,可以巧妙地将字母因子排序为与数字相同的顺序。

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?有什么聪明的想法吗?

I've found dplyr doesn't work super well with group_by() when dealing with different factor levels in each of the groups. 我发现当处理每个组中不同的因子水平时,dplyr与group_by()不能很好地配合。 So one work around is thinking of creating a new factor that's unique for each animal-letter combination and ordering that. 因此,一种解决方法是考虑为每个动物字母组合创建一个独特的新因素并对其进行排序。 First, we create an interaction variable with animal+letter and determine the proper order for each of the letters for the animals 首先,我们创建一个带有animal + letter的交互变量,并为动物的每个字母确定正确的顺序

new_order <- my_df %>% 
  group_by(animals) %>% 
  do(data_frame(al=levels(reorder(interaction(.$animals, .$letters, drop=TRUE), .$numbers)))) %>% 
  pull(al)

Now we create the interaction variable in the data we want to plot, use this new ordering, and finally change the labels so they look like just the letters again 现在,我们在要绘制的数据中创建交互变量,使用此新顺序,最后更改标签,使它们再次看起来像字母

my_df %>% 
  mutate(al=factor(interaction(animals, letters), levels=new_order)) %>%
  ggplot(aes(x = al, y = numbers)) +
    geom_point() + facet_wrap(~animals, ncol = 1, scales = 'free_x') +
    scale_x_discrete(breaks= new_order, labels=gsub("^.*\\.", "", new_order))

在此处输入图片说明

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)
)

my_df %>% group_by(animals) %>% 
  arrange(numbers, .by_group = T) %>% 
  mutate(lett = factor(interaction(animals,letters,  drop=TRUE))) -> my_df

ggplot(my_df, aes(x = reorder(lett, numbers), y = numbers)) +
  geom_point(size = 3) +
  facet_wrap(~animals, ncol = 1, scales = 'free_x') +
  scale_x_discrete(breaks = my_df$lett, labels=gsub("^.*\\.", "", my_df$lett))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM