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

时间:2018-05-23 07:58:31

标签: matlab sorting matrix grouping split-apply-combine

在矩阵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行。上面举例说明了一个例子。

1 个答案:

答案 0 :(得分:4)

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

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).'}, ...由于splitapply必须返回每个组的标量对象,因此需要告知输出是一个单元格,以便它可以返回一个矩阵。 (这可能不是最好的解释,但如果您尝试以单元格输出运行它,您将收到以下错误:

    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将输出单元格转换回数字数组。