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

其他回答

或者您可以使用包doBy

library(doBy)
dd <- orderBy(~-z+b, data=dd)

我通过下面的例子了解了秩序,这让我困惑了很长一段时间:

set.seed(1234)

ID        = 1:10
Age       = round(rnorm(10, 50, 1))
diag      = c("Depression", "Bipolar")
Diagnosis = sample(diag, 10, replace=TRUE)

data = data.frame(ID, Age, Diagnosis)

databyAge = data[order(Age),]
databyAge

此示例之所以有效,唯一的原因是顺序是按向量Age排序,而不是按数据帧数据中名为Age的列排序。

要看到这一点,请使用read.table创建一个完全相同的数据帧,列名称略有不同,并且不使用任何上述向量:

my.data <- read.table(text = '

  id age  diagnosis
   1  49 Depression
   2  50 Depression
   3  51 Depression
   4  48 Depression
   5  50 Depression
   6  51    Bipolar
   7  49    Bipolar
   8  49    Bipolar
   9  49    Bipolar
  10  49 Depression

', header = TRUE)

由于没有名为age的向量,上述order的行结构不再有效:

databyage = my.data[order(age),]

以下行之所以有效,是因为顺序根据my.data中的列年龄排序。

databyage = my.data[order(my.data$age),]

我认为这是值得张贴的,因为我被这个例子迷惑了这么久。如果这个帖子不适合这个线程,我可以删除它。

编辑:2014年5月13日

下面是按每列对数据帧进行排序而不指定列名的通用方法。下面的代码显示了如何从左到右或从右到左排序。如果每一列都是数字,这将起作用。我没有尝试添加字符列。

一两个月前,我在另一个网站的一篇旧帖子中找到了do.call代码,但这是经过广泛而艰难的搜索之后才发现的。我不确定我现在能不能重新安置那个职位。目前的线程是在R中订购data.frame的第一个热门线程。因此,我认为我的原始do.call代码的扩展版本可能有用。

set.seed(1234)

v1  <- c(0,0,0,0, 0,0,0,0, 1,1,1,1, 1,1,1,1)
v2  <- c(0,0,0,0, 1,1,1,1, 0,0,0,0, 1,1,1,1)
v3  <- c(0,0,1,1, 0,0,1,1, 0,0,1,1, 0,0,1,1)
v4  <- c(0,1,0,1, 0,1,0,1, 0,1,0,1, 0,1,0,1)

df.1 <- data.frame(v1, v2, v3, v4) 
df.1

rdf.1 <- df.1[sample(nrow(df.1), nrow(df.1), replace = FALSE),]
rdf.1

order.rdf.1 <- rdf.1[do.call(order, as.list(rdf.1)),]
order.rdf.1

order.rdf.2 <- rdf.1[do.call(order, rev(as.list(rdf.1))),]
order.rdf.2

rdf.3 <- data.frame(rdf.1$v2, rdf.1$v4, rdf.1$v3, rdf.1$v1) 
rdf.3

order.rdf.3 <- rdf.1[do.call(order, as.list(rdf.3)),]
order.rdf.3

这里有很多很好的答案,但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

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

dfOrder(myDf, columnIndices)

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

“psych”包中的dfOrder函数

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

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