我想按多列对数据帧进行排序。例如,对于下面的数据帧,我希望按列“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

当前回答

另一种选择是使用rgr包:

> library(rgr)
> gx.sort.df(dd, ~ -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

其他回答

或者,使用包扣减器

library(Deducer)
dd<- sortData(dd,c("z","b"),increasing= c(FALSE,TRUE))

这里有很多很好的答案,但dplyr提供了我唯一能快速、容易记住的语法(因此现在经常使用):

library(dplyr)
# sort mtcars by mpg, ascending... use desc(mpg) for descending
arrange(mtcars, mpg)
# sort mtcars first by mpg, then by cyl, then by wt)
arrange(mtcars , mpg, cyl, wt)

对于OP的问题:

arrange(dd, desc(z),  b)

    b x y z
1 Low C 9 2
2 Med D 3 1
3  Hi A 8 1
4  Hi A 9 1

您可以直接使用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()可以更方便/更直接地访问)。

如果SQL是自然生成的,sqldf包将按照Codd的意图处理ORDERBY。

德克的回答很好。它还强调了用于索引data.frames和data.tables的语法的一个关键区别:

## The data.frame way
dd[with(dd, order(-z, b)), ]

## The data.table way: (7 fewer characters, but that's not the important bit)
dd[order(-z, b)]

这两个调用之间的差异很小,但可能会产生重要的后果。特别是如果您编写生产代码和/或关注研究中的正确性,最好避免不必要的重复变量名。数据表帮助您做到这一点。

下面是一个重复变量名称可能会给您带来麻烦的示例:

让我们从Dirk的答案中改变上下文,并说这是一个更大项目的一部分,其中有很多对象名称,它们很长,很有意义;而不是dd,它被称为季度报告。它变成:

quarterlyreport[with(quarterlyreport,order(-z,b)),]

好的,好的。这没什么错。接下来,你的老板要求你在报告中包括上一季度的报告。你通过代码,在不同的地方添加一个对象最后一个季度报告,不知怎么的(到底是怎么回事?)你最终得到了这样的结果:

quarterlyreport[with(lastquarterlyreport,order(-z,b)),]

这不是你的意思,但你没有发现它,因为你做得很快,而且它位于一个类似代码的页面上。代码不会出错(没有警告和错误),因为R认为这就是你的意思。你希望无论谁读你的报告都能发现,但也许他们没有。如果您经常使用编程语言,那么这种情况可能非常熟悉。你会说这是个“错别字”。我会纠正你对老板说的“错别字”。

在data.table中,我们关注像这样的微小细节。因此,我们做了一些简单的操作,以避免两次键入变量名。非常简单的事情。我已经在dd的框架内自动评估了。你根本不需要with()。

而不是

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

只是

dd[order(-z, b)]

而不是

quarterlyreport[with(lastquarterlyreport,order(-z,b)),]

只是

quarterlyreport[order(-z,b)]

这是一个很小的区别,但也许有一天它会拯救你的脖子。在权衡这个问题的不同答案时,考虑将变量名称的重复次数作为决定的标准之一。有些答案有相当多的重复,其他答案没有。