使用dplyr按自定义顺序排列行

82

使用dplyr中的arrange函数,我们可以按升序或降序排列行。想知道如何按自定义顺序排列行,请参见MWE。

Reg <- rep(LETTERS[1:3], each = 2)
Res <- rep(c("Urban", "Rural"), times = 3)
set.seed(12345)
Pop <- rpois(n = 6, lambda = 500000)
df <- data.frame(Reg, Res, Pop)

df
   Reg   Res    Pop
1    A Urban 500414
2    A Rural 500501
3    B Urban 499922
4    B Rural 500016
5    C Urban 501638
6    C Rural 499274

df %>%
  arrange()

期望输出

   Reg   Res    Pop
5    C Urban 501638
6    C Rural 499274
1    A Urban 500414
2    A Rural 500501
3    B Urban 499922
4    B Rural 500016
3个回答

140

我们可以使用factor以自定义的方式改变order

df %>%
    arrange(factor(Reg, levels = LETTERS[c(3, 1, 2)]), desc(Res), desc(Pop))
#  Reg   Res    Pop
#1   C Urban 501638
#2   C Rural 499274
#3   A Urban 500414
#4   A Rural 500501
#5   B Urban 499922
#6   B Rural 500016

或者使用match来获取索引,然后在其上调用arrange

df %>%
    arrange(match(Reg, c("C", "A", "B")), desc(Res), desc(Pop))
如果我们有多个列需要按降序排列
df %>%
     arrange_at(2:3, desc) %>%
     arrange(match(Reg, c("C", "A", "B")))

2
感谢@akrun提供的好解决方案。有没有办法在不输入变量名称的情况下使用“desc”来处理所有剩余的变量?谢谢。 - MYaseen208
@MYaseen208 谢谢你的留言。我添加了另一个选项,希望它有所帮助。 - akrun
是的, echo @MYaseen208 的话,有没有办法将一对变量放在底部,但其他变量放在顶部?例如,如果我有20个变量,并且我想要其中2个在底部,这种方法似乎只适用于我在匹配中命名前18个变量。无论我使用什么desc()和!match,我总是得到未命名值在底部的结果。 - jzadra
1
给未来的观众一个小提示:第一种解决方案可以简化为 df %>% arrange(factor(Reg, levels = LETTERS[c(3,1,2)])) - user8248672
2
看起来,如果排序变量在 arrange 之外已经定义为有序因子,那么 arrange 的行为仍然是按字母顺序排序...怎么会这样? - Fons MA
@FonsMA 不太清楚您的评论。您能否发布一个小示例? - akrun

14

我使用了 slice() 函数:

   df %<>%
   slice(5,6,1:4)

1
我发现这是最简单和最易于理解的答案,但我发现我可以使用%>%而不是%<>%。 - Markm0705

4
使用 data.table
df1[order(factor(Reg,levels = LETTERS[c(3,1,2)]))]

这里的df1是一个data.table


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