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

How to rowwise-sort a matrix containing subgrouped data

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

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 行。上面演示了一个例子。

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

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 ) returns 组的行向量。组的数量是总行数除以组大小。 (为了更好的衡量,应该断言这是可以整除的,没有余数)。
  • splitapply( @(x){sort(x,2).'}, ... 因为 splitapply 必须 return 每组一个标量对象,所以需要告知输出是一个单元格,以便它可以 return一个矩阵。 (这可能不是最好的解释,但如果您尝试 运行 它 w/o 单元格输出,您将收到以下错误:

    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)}
    
  • 我执行了几个转置操作,因为这是 splitapply 所期望的。

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