代码之家  ›  专栏  ›  技术社区  ›  user9003011

如何对包含子组数据的矩阵进行按行排序

  •  2
  • user9003011  · 技术社区  · 8 年前

    在矩阵中 A ,每列表示一个输出变量,每行表示一个读数(共6行)。每个输出都有一个特定的子组大小(3行的组)。我需要 一 的元素将在每个子组中按垂直方向排序。

    A = [ 1 7 4; 4 9 3; 8 5 7; 2 9 1; 7 4 4; 8 1 3];
    % consecutive 3 rows is one subgroup, within which sorting is required.
    B = [1 5 3; 4 7 4; 8 9 7; 2 1 1; 7 4 3; 8 9 4]; % the expected result.
    

    我在考虑 B = splitapply(@sort,A,2) 但是 splitapply 不能这样叫。我怎样才能得到想要的结果?

    请注意,实际矩阵包含8列和300行。上面演示了一个示例。

    1 回复  |  直到 8 年前
        1
  •  4
  •   Dev-iL    8 年前

    最简单的解决方案是重塑数据,排序,然后排列:

    rps = 3; % rows per subgroup 
    B = permute(sort(reshape(A.',rps,size(A,2),[]),2),[2 1 3]);
    

    上面的结果是一个3x3x2数组,在我看来,它更容易使用,但是如果您希望输出如示例中所示,可以执行以下操作:

    B = reshape(permute(sort(reshape(A.',rps,size(A,2),[]),2),[2 3 1]),size(A));
    

    或者,你认为这是正确的 splitapply 在这里很有用,但需要做更多的工作。

    此命令用于示例数据,还应用于完整的数据集:

    b = cell2mat( splitapply( @(x){sort(x,2).'}, A.', repelem( 1:size(A,1)/rps, rps ) ).' );
    

    我来解释一下它的作用:

    • repelem( 1:size(A,1)/rps, rps ) 返回组的行向量。组的数量是行总数除以组大小。(为了很好地衡量,应该有一个断言,即这是可以除数的,没有余数)。
    • splitapply( @(x){sort(x,2).'}, ... 自从 拆分应用 必须按组返回一个标量对象,需要告知输出是一个单元格,以便返回矩阵。(这可能不是最好的解释,但是如果您尝试在没有单元输出的情况下运行它,您将得到以下错误:

      The function 'sort' returned a non-scalar value when applied to the 1st group of data.
      
      To compute nonscalar values for each group, create an anonymous function to return each value in a scalar cell:
      
          @(x1){sort(x1)}
      
    • 我做了几次换位操作,因为这是 拆分应用 预期。

    • 我用过 cell2mat 将输出单元格转换回数字数组。