如何以整洁的方式重新排序因子水平?

31
嗨,我通常使用以下代码来重新排序ggplot或其他类型的图表中的条形图。
普通图表(无序)
library(tidyverse)
iris.tr <-iris %>% group_by(Species) %>% mutate(mSW = mean(Sepal.Width)) %>%
  select(mSW,Species) %>% 
  distinct()
ggplot(iris.tr,aes(x = Species,y = mSW, color = Species)) +
  geom_point(stat = "identity")

订购因子 + 有序绘图
iris.tr$Species <- factor(iris.tr$Species,
                          levels = iris.tr[order(iris.tr$mSW),]$Species,
                          ordered = TRUE)
ggplot(iris.tr,aes(x = Species,y = mSW, color = Species)) + 
  geom_point(stat = "identity")

因素线对我来说非常不舒服,我想知道为什么`arrange()`或其他函数不能简化这个过程。我是不是漏掉了什么?
注意: 这个方法不起作用,但我想知道在tidyverse中是否存在类似的方法。
iris.tr <-iris %>% group_by(Species) %>% mutate(mSW = mean(Sepal.Width)) %>%
  select(mSW,Species) %>% 
  distinct() %>% 
  arrange(mSW)
ggplot(iris.tr,aes(x = Species,y = mSW, color = Species)) + 
  geom_point(stat = "identity")

4
注意:在标识符中不应使用 .,因为在使用 S3 分发时它具有特定的含义(请改用 _);并且不应将 T 用于 TRUE,因为它不是保留字,可以被重新定义(对于不端者可能设置为 T = FALSE)。 - Konrad Rudolph
也许我完全错了,但我认为这是在 R 中命名标识符的正确方式。我在 Google 的 R 代码风格指南 中看到过。 - David Mas
1
谷歌的风格指南通常有点糟糕。忽略它们。这里有一个更好的R语言风格指南:http://style.tidyverse.org/ — 我不同意其中一些观点(文件名中的大写字母?!什么鬼),但它绝对是可接受的,并且在R语言中被广泛使用。 - Konrad Rudolph
好的,看起来很有趣,我会去看看!编辑:将 T 改为 TRUE。 - David Mas
4个回答

24

使用 ‹forcats› 库:

iris.tr %>%
    mutate(Species = fct_reorder(Species, mSW)) %>%
    ggplot() +
    aes(Species, mSW, color = Species) +
    geom_point()

fct_reorderreorder有什么区别? - Julien
1
@Julien,它大多数情况下非常相似,但(像大多数r-lib和tidyverse函数一样)它执行更严格的错误检查,因此更加健壮。我通常不会使用fct_reorder替代reorder,除非OP已经在使用tidyverse包,在这种情况下,我建议始终使用核心R功能的替代品,现代重新实现只是更好了那么一点点。 - Konrad Rudolph

13

使用基础函数重新排序因子:

iris.ba = iris
iris.ba$Species = with(iris.ba, reorder(Species, Sepal.Width, mean))

翻译为 dplyr

iris.tr = iris %>% mutate(Species = reorder(Species, Sepal.Width, mean))

接下来,您可以按照您的问题继续总结和绘图。


几点评论:重新排序因子是修改数据列。用于修改数据列的 dplyr 命令是 mutate。所有的 arrange 只是重新排列行,这对因子的级别没有影响,因此不会影响 ggplot 中图例或坐标轴的顺序。

所有因子都有其级别的顺序。有序(ordered = TRUE)和常规因子之间的区别在于模型中如何设置对比度。只有在因子级别具有有意义的等级顺序时(例如“低”、“中”、“高”),才应使用 ordered = TRUE,即使如此它也只在构建模型并且不希望默认对比度将所有内容与参考水平进行比较时才有作用。


很高兴了解到重新排序。那么reorder()ordered=TRUE之间有什么区别呢?我的意思是,它们是否修改因子的不同元素或类似的东西? - David Mas
我看到它使用了一个具有得分向量的属性。明白了! - David Mas
reorder 函数可以改变因子(或有序因子)水平的顺序。正如我所说,所有的因子都有它们水平的顺序。使用 factor(..., ordered = TRUE) 可以创建一个带有 "ordered" 和 "factor" 类的对象,该对象对于对比和某些比较具有特殊行为。(对比,如我在问题中提到的,您可以使用 <> 来比较元素。)除非您需要这些特殊行为,否则不需要使用 ordered = TRUE - Gregor Thomas

2
如果您恰好有一个需要排序的字符向量,例如:
iris2 <- iris %>% 
    mutate(Species = as.character(Species)) %>% 
    group_by(Species) %>% 
    mutate(mean_sepal_width = mean(Sepal.Width)) %>% 
    ungroup()

您也可以使用 forcats::as_factor 函数的行为来排序因子水平:

"与基础 R 相比,此函数按它们出现的顺序创建水平"

library(forcats)
iris2 %>% 
    # Change the order
    arrange(mean_sepal_width) %>%  
    # Create factor levels in the order in which they appear
    mutate(Species = as_factor(Species)) %>%
    ggplot() +
    aes(Species, Sepal.Width, color = Species) +
    geom_point()

注意x轴上的物种名称并非按字母顺序排列,而是按其 mean_sepal_width 值递增排序。删除包含as_factor 的行以查看差异。

-1

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