【问题标题】:split a matrix according to a column with matlab.使用matlab根据列拆分矩阵。
【发布时间】:2013-08-29 07:43:19
【问题描述】:
A = [1,4,2,5,10
     2,4,5,6,2
     2,1,5,6,10
     2,3,5,4,2]

我想在最后一列把它分成两个矩阵 A -> B 和 C

B =  [1,4,2,5,10
      2,1,5,6,10]
C = [2,4,5,6,2
     2,3,5,4,2]

另外,这种方法也可以应用于大矩阵,比如100*22的矩阵,matlab根据最后一列的值分成9组。

【问题讨论】:

  • 你能详细解释一下你想要达到的目标吗?

标签: matlab matrix split


【解决方案1】:

使用logical indexing

B=A(A(:,end)==10,:);
C=A(A(:,end)==2,:);

返回

>> B
B =
     1     4     2     5    10
     2     1     5     6    10

>> C
C =
     2     4     5     6     2
     2     3     5     4     2

编辑:作为对 Dan 评论的回复,这里是一般情况的扩展

e = unique(A(:,end));
B = cell(size(e));
for k = 1:numel(e)
    B{k} = A(A(:,end)==e(k),:);
end

或更紧凑的方式

B=arrayfun(@(x) A(A(:,end)==x,:), unique(A(:,end)), 'UniformOutput', false);

所以

A =
     1     4     2     5    10
     2     4     5     6     2
     2     1     5     6    10
     2     3     5     4     2
     0     3     1     4     9
     1     3     4     5     1
     1     0     4     5     9
     1     2     4     3     1

你得到单元格数组B的元素中的矩阵

>> B{1}
ans =
     1     3     4     5     1
     1     2     4     3     1

>> B{2}
ans =
     2     4     5     6     2
     2     3     5     4     2

>> B{3}
ans =
     0     3     1     4     9
     1     0     4     5     9

>> B{4}
ans =
     1     4     2     5    10
     2     1     5     6    10

【讨论】:

  • 如果有 9 个组,这将变得乏味
  • @Dan 它只需要一个 for 循环来概括它。我将其添加到答案中。
  • 这更好 - 给出了与我相同的结果,但在这种情况下,循环方法似乎比矢量化方法更快! +1
【解决方案2】:

这是一种通用方法,适用于任何大小矩阵的最后一列中的任意数量的数字:

A = [1,4,2,5,10
     2,4,5,6,2
     1,1,1,1,1
     2,1,5,6,10
     2,3,5,4,2
     0,0,0,0,2];

先按最后一列排序(方法很多,不知道这样好不好)

[~, order] = sort(A(:,end));
As = A(order,:);

然后创建一个向量,其中包含在最后一个列中出现多少相同数字的行(即每组有多少行)

rowDist = diff(find([1; diff(As(:, end)); 1]));

请注意,对于我的示例数据,rowDist 将等于 [1 3 2],因为有 1 个1、3 个2s 和 2 个10s。 现在使用mat2cell 按这些行分组进行拆分:

Ac = mat2cell(As, rowDist);

如果你真的想要,现在可以将其拆分为单独的矩阵(但我怀疑你会这样做)

Ac{:}

结果

ans =

   1   1   1   1   1

ans =

   0   0   0   0   2
   2   3   5   4   2
   2   4   5   6   2

ans =

    1    4    2    5   10
    2    1    5    6   10

但我想你会发现Ac 本身更有用

编辑:

很多解决方案所以不妨做一个时间比较:

A = [...
     1     4     2     5    10
     2     4     5     6     2
     2     1     5     6    10
     2     3     5     4     2
     0     3     1     4     9
     1     3     4     5     3
     1     0     4     5     9
     1     2     4     3     1];

A = repmat(A, 1000, 1);

tic
for l = 1:100
  [~, y] = sort(A(:,end));
  As = A(y,:);
  rowDist = diff(find([1; diff(As(:, end)); 1]));
  Ac = mat2cell(As, rowDist);
end
toc

tic
for l = 1:100
  D=arrayfun(@(x) A(A(:,end)==x,:), unique(A(:,end)), 'UniformOutput', false);
end
toc

tic
for l = 1:100
  for k = 1:numel(e)
      B{k} = A(A(:,end)==e(k),:);
  end
end
toc

tic
for l = 1:100
  Bb = sort(A(:,end)); 
  [~,b] = histc(A(:,end), Bb([diff(Bb)>0;true]));
  C = accumarray(b, (1:size(A,1))', [], @(r) {A(r,:)} );
end
toc

导致

Elapsed time is 0.053452 seconds.
Elapsed time is 0.17017 seconds.
Elapsed time is 0.004081 seconds.
Elapsed time is 0.22069 seconds.

因此,即使对于大矩阵,循环方法仍然是最快的。

【讨论】:

    【解决方案3】:

    accumarrayhistc 结合使用:

    % Example data (from Mohsen Nosratinia)
    A = [...
         1     4     2     5    10
         2     4     5     6     2
         2     1     5     6    10
         2     3     5     4     2
         0     3     1     4     9
         1     3     4     5     1
         1     0     4     5     9
         1     2     4     3     1];
    
    % Get the proper indices to the specific rows
    B = sort(A(:,end)); 
    [~,b] = histc(A(:,end), B([diff(B)>0;true]));
    
    % Collect all specific rows in their specific groups
    C = accumarray(b, (1:size(A,1))', [], @(r) {A(r,:)} );
    

    结果:

    >> C{:}
    ans =
         1     3     4     5     1
         1     2     4     3     1
    ans =
         2     3     5     4     2
         2     4     5     6     2
    ans =
         0     3     1     4     9
         1     0     4     5     9
    ans =
         2     1     5     6    10
         1     4     2     5    10
    

    注意

    B = sort(A(:,end)); 
    [~,b] = histc(A(:,end), B([diff(B)>0;true]));
    

    也可以写成

    [~,b] = histc(A(:,end), unique(A(:,end)));
    

    unique 不是内置的,因此可能会更慢,尤其是当它全部用于循环时。

    还请注意,行的顺序已更改 w.r.t。他们在原始矩阵中的顺序。如果顺序很重要,您将不得不输入另一个sort

    C = accumarray(b, (1:size(A,1))', [], @(r) {A(sort(r),:)} );
    

    【讨论】:

      猜你喜欢
      • 2016-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多