【问题标题】:Ordering factors in each facet of ggplot by y-axis value按 y 轴值对 ggplot 的每个方面的因子进行排序
【发布时间】:2018-01-10 03:09:23
【问题描述】:

比方说,在 R 中,我有一个数据框字母、数字和动物,我想以图形方式检查这三者之间的关系。我可以做类似的事情。

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 轴的顺序。根据example,这很容易在没有方面的情况下完成。 我什至可以为每只动物制作一个有序的图形,然后将它们与 grid.arrange 绑定在一起,如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)

不过,我并不特别喜欢这种解决方案,因为它不容易推广到有很多方面的情况。

我宁愿做类似的事情 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')

这不太奏效,因为顺序最终会在刻面包装之前而不是之后生效,因此每个面板的标签顺序并不完全正确。

有什么聪明的想法吗?

【问题讨论】:

    标签: r ggplot2


    【解决方案1】:

    我发现 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))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-11-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-28
        • 1970-01-01
        • 1970-01-01
        • 2022-01-01
        相关资源
        最近更新 更多