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

当前回答

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

其他回答

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

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

为了完整起见,由于没有太多关于按列编号排序的内容。。。可以肯定的是,这通常是不可取的(因为列的顺序可能会改变,为错误铺平道路),但在某些特定情况下(例如,当您需要快速完成工作,并且没有列改变顺序的风险),这可能是最明智的做法,尤其是在处理大量列时。

在这种情况下,do.call()来拯救:

ind <- do.call(what = "order", args = iris[,c(5,1,2,3)])
iris[ind, ]

##        Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
##    14           4.3         3.0          1.1         0.1     setosa
##    9            4.4         2.9          1.4         0.2     setosa
##    39           4.4         3.0          1.3         0.2     setosa
##    43           4.4         3.2          1.3         0.2     setosa
##    42           4.5         2.3          1.3         0.3     setosa
##    4            4.6         3.1          1.5         0.2     setosa
##    48           4.6         3.2          1.4         0.2     setosa
##    7            4.6         3.4          1.4         0.3     setosa
##    (...)

或者您可以使用包doBy

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

假设您有一个data.frame a,并且希望使用名为x降序的列对其进行排序。调用排序后的数据。frame newdata

newdata <- A[order(-A$x),]

如果需要升序,请将“-”替换为空。你可以吃类似的东西

newdata <- A[order(-A$x, A$y, -A$z),]

其中x和z是data.frame A中的一些列。这意味着按照x降序、y升序和z降序对data.frameA进行排序。

或者,使用包扣减器

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