如何按所有列对矩阵/ data.frame进行排序

wen*_*wen 3 sorting r matrix

我有一个矩阵,例如:

a = rep(0:1, each=4)
b = rep(rep(0:1, each=2), 2)
c = rep(0:1, times=4)
mat = cbind(c,b,a)
Run Code Online (Sandbox Code Playgroud)

我需要对这个矩阵的所有列进行排序.我知道如何通过排序特定列(即有限数量的列)来完成此操作.

mat[order(mat[,"c"],mat[,"b"],mat[,"a"]),]
     c b a
[1,] 0 0 0
[2,] 0 0 1
[3,] 0 1 0
[4,] 0 1 1
[5,] 1 0 0
[6,] 1 0 1
[7,] 1 1 0
[8,] 1 1 1
Run Code Online (Sandbox Code Playgroud)

但是,我需要一种通用的方法来执行此操作而不调用任何列名,因为我可以有任意数量的列.我如何按大量列排序?

bgo*_*dst 8

这是一个简洁的解决方案:

mat[do.call(order,as.data.frame(mat)),];
##      c b a
## [1,] 0 0 0
## [2,] 0 0 1
## [3,] 0 1 0
## [4,] 0 1 1
## [5,] 1 0 0
## [6,] 1 0 1
## [7,] 1 1 0
## [8,] 1 1 1
Run Code Online (Sandbox Code Playgroud)

调用以as.data.frame()直观的方式将矩阵转换为data.frame,即每个矩阵列成为新data.frame中的列表组件.由此,您可以通过将矩阵order()的分层形式作为第二个参数传递,将每个矩阵列有效地传递给单个调用do.call().

这适用于任意数量的列.


这不是一个愚蠢的问题.其原因mat[order(as.data.frame(mat)),]不工作是因为order()不是命令由行data.frames.基于从左到右排序列向量(这是我的解决方案所做的),而不是返回data.frame的行顺序,它基本上将data.frame展平为单个大向量并对其进行排序.因此,事实上,order(as.data.frame(mat))等同于order(mat)矩阵也被视为平面向量.对于您的特定数据,这将返回24个索引,理论上可以用于索引(作为向量)原始矩阵mat,但是因为在表达式中mat[order(as.data.frame(mat)),]您尝试使用它们来仅mat索引某些索引的行维度超过最高行索引,因此您得到"下标越界"错误.

?do.call.我认为我不能比帮助页面更好地解释它; 看看这些例子,与它们一起玩,直到你了解它是如何工作的.基本上,当您要传递给函数的单个调用的参数被捕获在列表中时,您需要调用它.你不能传递列表本身(因为那时你没有传递预期的参数,你传递一个包含预期参数的列表),所以必须有一个原始函数从列表中"解开"参数功能调用.这是编程语言中的常见原语,其中函数是第一类对象,特别是(除了R do.call())JavaScript apply(),Python(已弃用)apply()和vim call().