11

假设我有

arr = 2 1 3
      1 2 3
      1 1 2

我怎样才能把它分类到下面?

arr = 1 1 2
      1 2 3
      2 1 3

也就是说,首先按第一列,然后按第二列,依此类推。

4

4 回答 4

20

你所追求的功能是order(我是如何得出这个结论的——我的第一个想法是“好吧,排序,怎么样sort?”。尝试过sort(arr)它看起来像是arr一个向量而不是按行排序。看着?sort,我明白了在“另请参阅:对多个order变量进行排序或重新排序。”)。

看着?order,我看到order(x,y,z, ...)将 order by x,break ties by y,break further ties by z,依此类推。太好了 - 我所要做的就是传递 to 的每一列arrorder做到这一点。(在示例部分中甚至还有一个示例?order):

order( arr[,1], arr[,2], arr[,3] ) 
# gives 3 2 1: row 3 first, then row 2, then row 1.
# Hence:
arr[ order( arr[,1], arr[,2], arr[,3] ), ]
#     [,1] [,2] [,3]
#[1,]    1    1    2
#[2,]    1    2    3
#[3,]    2    1    3

伟大的!


arr[,i]但是我必须为每一列写出有点烦人arr- 如果我不知道它有多少列怎么办?

好吧,这些示例也展示了如何做到这一点:使用do.call. 基本上,你这样做:

do.call( order, args )

其中args是参数列表order。因此,如果您可以从 的每一列中列出一个列表,arr那么您可以将其用作args.

一种方法是转换arr为数据框,然后转换为列表——这将自动为列表的每个元素放置一列:

arr[ do.call( order, as.list(as.data.frame(arr)) ), ]

as.list(as.data.frame有点笨拙-当然还有其他方法可以创建列表,例如的list[[i]]iarr,但这只是其中一种。

于 2012-05-09T00:45:29.347 回答
18

这会起作用:

arr[do.call(order, lapply(1:NCOL(arr), function(i) arr[, i])), ]

它正在做的是:

arr[order(arr[, 1], arr[, 2], arr[ , 3]), ]

除了它允许矩阵中有任意数量的列。

于 2012-05-09T00:42:24.610 回答
1

我写了这个小函数,它也可以降序 cols 允许选择要排序的列及其顺序

ord.mat = function(M, decr = F, cols = NULL){
    if(is.null(cols))
      cols = 1: ncol(M)
    out = do.call( "order", as.data.frame(M[,cols]))
    if (decr)
      out = rev(out)
    return(M[out,])
}
于 2013-08-01T21:41:33.220 回答
1

我遇到了类似的问题,解决方案似乎简单而优雅:

t(apply(t(yourMatrix),2,sort))
于 2016-07-12T22:46:03.243 回答