按照 ggplot 中每个方面的 y 轴值排序因素

5
假设在 R 中,我有一个数据框 letters、numbers 和 animals,并且我想通过图形来检查它们之间的关系。可以使用以下代码:
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')

我想要得到类似这样的东西。 无序字母

然而,我希望x轴的顺序取决于y轴的顺序。在没有分面的情况下,这很容易做到,就像这个例子所示。 我甚至可以为每个动物制作一个有序的图形,然后使用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)

有序动物图示

虽然这个解决方案不是很通用,但我并不是特别喜欢它,因为当有很多方面需要考虑时,它并不容易适用。

我更喜欢做一些像这样的事情 ggplot(my_df, aes(x = y_ordered_by_facet(letters, by = numbers), y = numbers)) + geom_point() + facet_wrap(~animals, ncol = 1, scales = 'free_x')

其中y_ordered是某个函数,聪明地将字母因子排序成与数字相同的顺序。

有些接近这个目标的东西,但似乎并不能完全实现

ggplot(my_df, aes(x = reorder(letters, numbers), y = numbers)) +
     geom_point() + facet_wrap(~animals, ncol = 1, scales = 'free_x')

这不太可行,因为顺序在分面包装之前就生效了,导致每个面板中的标签顺序不完全正确。almost ordered有什么聪明的想法吗?
2个回答

13

我发现当处理每个组中的不同因子水平时,dplyr在使用group_by()函数时效果不是很好。因此,一种解决方法是考虑创建一个新的因子,针对每个动物字母组合都是唯一的并对其进行排序。首先,我们创建一个动物+字母的交互变量,并确定每个动物字母对应的合适顺序。

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

现在我们在要绘制的数据中创建交互变量,使用这个新的顺序,最后更改标签,使它们再次看起来只是字母

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

输入图像描述


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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接