如何按多个列排序数据框?
我想通过多列对数据框进行排序。 例如,在下面的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()
以便于更直接地访问)。
您的选择
order
从base
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
您也可以使用Hadley在上述线程中指出的plyr
的arrange()
函数:
library(plyr)
arrange(dd,desc(z),b)
基准测试:请注意,由于存在很多冲突,我在一个新的R会话中加载了每个软件包。 特别是加载doBy包导致sort
返回“下面的对象从'x(位置17)'被掩盖:b,x,y,z”,并且加载Deducer包将覆盖来自Kevin的sort.data.frame
赖特或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)
由于附着/分离,似乎与microbenchmark不兼容。
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
s和data.table
s的语法中的一个关键区别:
## 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
在不同的地方,不知怎么你结束了这个(如何在地球上?):
quarterlyreport[with(lastquarterlyreport,order(-z,b)),]
这不是你的意思,但你没有发现它,因为你做得很快,而且它依赖于类似代码的页面。 代码不会翻倒(没有警告和错误),因为R认为它是你的意思。 你希望看到你的报告的人看到它,但也许他们没有。 如果你使用编程语言很多,那么这种情况可能会让人很熟悉。 这是一个你会说的“打字错误”。 我会解决你对老板说的“打字错误”。
在data.table
我们关注这样的细节。 所以我们做了一些简单的事情来避免两次输入变量名。 一些非常简单的东西。 i
已经自动地在dd
帧内dd
进行了评估。 with()
完全不需要。
代替
dd[with(dd, order(-z, b)), ]
只是
dd[order(-z, b)]
而不是
quarterlyreport[with(lastquarterlyreport,order(-z,b)),]
只是
quarterlyreport[order(-z,b)]
这是一个非常小的差异,但它可能只会挽救你的脖子有一天。 在权衡这个问题的不同答案时,考虑将变量名称的重复计为您决定的标准之一。 有些答案有不少重复,其他答案没有。
链接地址: http://www.djcxy.com/p/1913.html上一篇: How to sort a dataframe by multiple column(s)?
下一篇: How do I sort an NSMutableArray with custom objects in it?