我想按多列对数据帧进行排序。例如,对于下面的数据帧,我希望按列“z”(降序)排序,然后按列“b”(升序)排序:

dd <- data.frame(b = factor(c("Hi", "Med", "Hi", "Low"), 
      levels = c("Low", "Med", "Hi"), ordered = TRUE),
      x = c("A", "D", "A", "C"), y = c(8, 3, 9, 9),
      z = c(1, 1, 1, 2))
dd
    b x y z
1  Hi A 8 1
2 Med D 3 1
3  Hi A 9 1
4 Low C 9 2

当前回答

当我想自动化n列的排序过程时,我正在与上述解决方案作斗争,因为每一列的列名都可能不同。我从psych包中找到了一个非常有用的功能,可以直接实现这一点:

dfOrder(myDf, columnIndices)

其中columnIndex是一个或多个列的索引,按要对其排序的顺序排列。此处提供更多信息:

“psych”包中的dfOrder函数

其他回答

为了完整起见:您还可以使用BBmisc包中的sortByCol()函数:

library(BBmisc)
sortByCol(dd, c("z", "b"), asc = c(FALSE, TRUE))
    b x y z
4 Low C 9 2
2 Med D 3 1
1  Hi A 8 1
3  Hi A 9 1

性能比较:

library(microbenchmark)
microbenchmark(sortByCol(dd, c("z", "b"), asc = c(FALSE, TRUE)), times = 100000)
median 202.878

library(plyr)
microbenchmark(arrange(dd,desc(z),b),times=100000)
median 148.758

microbenchmark(dd[with(dd, order(-z, b)), ], times = 100000)
median 115.872

Dirk的回答很好,但如果您需要排序来持久化,您需要将排序应用回数据帧的名称。使用示例代码:

dd <- dd[with(dd, order(-z, b)), ] 

有了凯文·赖特(Kevin Wright)在R维基的提示部分发布的这个(非常有用的)功能,这很容易实现。

sort(dd,by = ~ -z + b)
#     b x y z
# 4 Low C 9 2
# 2 Med D 3 1
# 1  Hi A 8 1
# 3  Hi A 9 1

dplyr中的arrange()是我最喜欢的选项。使用管道操作员,从最不重要的方面转到最重要的方面

dd1 <- dd %>%
    arrange(z) %>%
    arrange(desc(x))

您可以直接使用order()函数,而无需使用附加工具——请参阅这个更简单的答案,它使用了示例(order)代码顶部的技巧:

R> dd[with(dd, order(-z, b)), ]
    b x y z
4 Low C 9 2
2 Med D 3 1
1  Hi A 8 1
3  Hi A 9 1

两年多后编辑:只是被问到如何按列索引进行编辑。答案是简单地将所需的排序列传递给order()函数:

R> dd[order(-dd[,4], dd[,1]), ]
    b x y z
4 Low C 9 2
2 Med D 3 1
1  Hi A 8 1
3  Hi A 9 1
R> 

而不是使用列的名称(使用with()可以更方便/更直接地访问)。