我想按多列对 data.frame 进行排序。例如,对于下面的 data.frame,我想按列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
您可以直接使用order()
函数而无需使用附加工具 - 请参阅这个更简单的答案,该答案使用example(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
大约 2 年多后编辑:只是通过列索引询问如何执行此操作。答案是简单地将所需的排序列传递给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()
更容易 / 更直接访问)。
base
order
dplyr
arrange
setorder
和setorderv
从data.table
plyr
arrange
taRifx
sort
orderBy
从doBy
sortData
从Deducer
大多数情况下你应该使用dplyr
或data.table
解决方案,除非重要性没有依赖性,在这种情况下使用base::order
。
我最近将 sort.data.frame 添加到 CRAN 包中,使其类兼容,如下所述: 为 sort.data.frame 创建通用 / 方法一致性的最佳方法?
因此,给定 data.frame dd,您可以按如下方式排序:
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))
library(taRifx)
sort(dd, f= ~ -z + b )
如果您是此功能的原作者之一,请与我联系。关于公共领域的讨论在这里: http : //chat.stackoverflow.com/transcript/message/1094290#1094290
您也可以使用plyr
的arrange()
函数,正如 Hadley 在上面的主题中指出的那样:
library(plyr)
arrange(dd,desc(z),b)
基准:请注意,由于存在大量冲突,因此我将每个包加载到新的 R 会话中。特别是加载 doBy 包会导致sort
返回 “以下对象被屏蔽'x(位置 17)':b,x,y,z”,并且加载 Deducer 包会覆盖 Kevin 的sort.data.frame
Wright 或 taRifx 包。
#Load each time
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))
library(microbenchmark)
# Reload R between benchmarks
microbenchmark(dd[with(dd, order(-z, b)), ] ,
dd[order(-dd$z, dd$b),],
times=1000
)
中位数时间:
dd[with(dd, order(-z, b)), ]
778
dd[order(-dd$z, dd$b),]
788
library(taRifx)
microbenchmark(sort(dd, f= ~-z+b ),times=1000)
中位时间: 1,567
library(plyr)
microbenchmark(arrange(dd,desc(z),b),times=1000)
中位时间: 862
library(doBy)
microbenchmark(orderBy(~-z+b, data=dd),times=1000)
中位时间: 1,694
请注意,doBy 需要花费大量时间来加载包。
library(Deducer)
microbenchmark(sortData(dd,c("z","b"),increasing= c(FALSE,TRUE)),times=1000)
无法使 Deducer 加载。需要 JGR 控制台。
esort <- function(x, sortvar, ...) {
attach(x)
x <- x[with(x,order(sortvar,...)),]
return(x)
detach(x)
}
microbenchmark(esort(dd, -z, b),times=1000)
由于连接 / 分离,似乎与微基准不兼容。
m <- microbenchmark(
arrange(dd,desc(z),b),
sort(dd, f= ~-z+b ),
dd[with(dd, order(-z, b)), ] ,
dd[order(-dd$z, dd$b),],
times=1000
)
uq <- function(x) { fivenum(x)[4]}
lq <- function(x) { fivenum(x)[2]}
y_min <- 0 # min(by(m$time,m$expr,lq))
y_max <- max(by(m$time,m$expr,uq)) * 1.05
p <- ggplot(m,aes(x=expr,y=time)) + coord_cartesian(ylim = c( y_min , y_max ))
p + stat_summary(fun.y=median,fun.ymin = lq, fun.ymax = uq, aes(fill=expr))
(线从下四分位数延伸到上四分位数,点是中位数)
鉴于这些结果和称重简单性与速度,我必须点头arrange
在plyr
包中 。它具有简单的语法,但几乎与基本的 R 命令一样快速,并且具有复杂的阴谋。通常辉煌的哈德利威克姆工作。我唯一的抱怨是它打破了标准的 R 术语,其中排序对象被sort(object)
调用,但我理解为什么 Hadley 这样做是由于上面链接的问题中讨论的问题。
德克的答案很棒。它还强调了用于索引data.frame
和data.table
的语法的主要区别:
## 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)]
这两个电话之间的差异很小,但它可能会产生重要影响。特别是如果您编写生产代码和 / 或关注研究中的正确性,最好避免不必要的重复变量名称。 data.table
可以帮助您实现这一目标。
这是一个如何重复变量名称可能会让您陷入麻烦的示例:
让我们从 Dirk 的答案中改变背景,并说这是一个更大的项目的一部分,其中有很多对象名称,它们很长很有意义; 而不是dd
它被称为quarterlyreport
。它成为了 :
quarterlyreport[with(quarterlyreport,order(-z,b)),]
好的。没有错。接下来,您的老板要求您在报告中包含上一季度的报告。你lastquarterlyreport
你的代码,在各个地方添加一个对象lastquarterlyreport
并以某种方式(地球上怎么样?)你最终得到这个:
quarterlyreport[with(lastquarterlyreport,order(-z,b)),]
这不是你的意思,但你没有发现它,因为你做得很快,而且它坐落在一个类似代码的页面上。代码不会失败(没有警告也没有错误),因为 R 认为这就是你的意思。你希望看到你的报告的人发现它,但也许他们没有。如果您经常使用编程语言,那么这种情况可能都是熟悉的。你会说这是一个 “错字”。我会解决你对老板说的 “拼写错误”。
在data.table
我们关注像这样的微小细节。所以我们做了一些简单的事情,以避免两次输入变量名。非常简单。 i
已经在dd
的框架内自动进行了评估。你根本不需要with()
。
代替
dd[with(dd, order(-z, b)), ]
只是
dd[order(-z, b)]
而不是
quarterlyreport[with(lastquarterlyreport,order(-z,b)),]
只是
quarterlyreport[order(-z,b)]
这是一个非常小的差异,但它可能只是有一天挽救你的脖子。权衡此问题的不同答案时,请考虑将变量名称的重复计算为您决定的标准之一。有些答案有不少重复,有些则没有。