如何按所有列对矩阵进行排序

Kar*_*ick 11 sorting r

假设我有

arr = 2 1 3
      1 2 3
      1 1 2
Run Code Online (Sandbox Code Playgroud)

我该如何将其分类到下面?

arr = 1 1 2
      1 2 3
      2 1 3
Run Code Online (Sandbox Code Playgroud)

也就是说,首先是第一列,然后是第二列等.

mat*_*fee 20

你所追求的功能是order(我是如何得出这个结论的 - 我的第一个想法是"好,排序,怎么样sort?".尝试sort(arr)看起来像是arr一个矢量而不是行的方式.看着?sort,我看到了在"另请参阅:order多个变量进行排序或重新排序.").

看着?order,我看到order(x,y,z, ...)它将依次排序x,打破关系y,打破进一步的关系z,等等.大-所有我需要做的就是通过在每列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
Run Code Online (Sandbox Code Playgroud)

大!


但是我必须arr[,i]每一列写出来有点烦人arr- 如果我不知道它预先有多少列呢?

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

do.call( order, args )
Run Code Online (Sandbox Code Playgroud)

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

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

arr[ do.call( order, as.list(as.data.frame(arr)) ), ]
Run Code Online (Sandbox Code Playgroud)

as.list(as.data.frame有点缺憾-当然也有其他的方式来创建这样一个列表,list[[i]]i的列arr,但是这仅仅是一个.


Dav*_*son 16

这可行:

arr[do.call(order, lapply(1:NCOL(arr), function(i) arr[, i])), ]
Run Code Online (Sandbox Code Playgroud)

它正在做的是:

arr[order(arr[, 1], arr[, 2], arr[ , 3]), ]
Run Code Online (Sandbox Code Playgroud)

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