【问题标题】:How to sort a matrix/data.frame by all columns如何按所有列对矩阵/数据框进行排序
【发布时间】:2015-04-07 03:01:29
【问题描述】:

我有一个矩阵,例如:

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)

我需要对该矩阵的所有列进行排序。我知道如何通过对特定列(即有限数量的列)进行排序来做到这一点。

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

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

【问题讨论】:

    标签: r sorting matrix


    【解决方案1】:

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

    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
    

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

    这适用于任意数量的列。


    这不是一个愚蠢的问题。 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()

    【讨论】:

    • 我希望这不是一个愚蠢的问题:您能否解释一下为什么“mat[order(as.data.frame(mat)), ]”不起作用?我只是不太明白“do.call()”。我应该什么时候考虑使用它?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多