在MATLAB中展开矩阵的最快方法是什么?

时间:2014-02-10 22:21:38

标签: performance matlab optimization matrix

如何转换矩阵:

[ 0.12 0.23 0.34 ;
  0.45 0.56 0.67 ;
  0.78 0.89 0.90 ] 

进入带有一堆行的'坐标'矩阵?

[ 1 1 0.12 ;
  1 2 0.23 ;
  1 3 0.34 ;
  2 1 0.45 ;
  2 2 0.56 ;
  2 3 0.67 ;
  3 1 0.78 ;
  3 2 0.89 ;
  3 3 0.90 ]

(行的排列无关紧要,只关键数据在此结构中)

现在我正在使用for循环,但这需要很长时间。

4 个答案:

答案 0 :(得分:9)

以下是使用ind2sub的选项:

mat= [ 0.12 0.23 0.34 ;
  0.45 0.56 0.67 ;
  0.78 0.89 0.90 ] ;

[I,J] = ind2sub(size(mat), 1:numel(mat));
r=[I', J', mat(:)]

r =

    1.0000    1.0000    0.1200
    2.0000    1.0000    0.4500
    3.0000    1.0000    0.7800
    1.0000    2.0000    0.2300
    2.0000    2.0000    0.5600
    3.0000    2.0000    0.8900
    1.0000    3.0000    0.3400
    2.0000    3.0000    0.6700
    3.0000    3.0000    0.9000

注意与您的示例相比,索引相反。

答案 1 :(得分:6)

A = [ .12 .23 .34 ;
      .45 .56 .67 ;
      .78 .89 .90 ];

[ii jj] = meshgrid(1:size(A,1),1:size(A,2));
B = A.';
R = [ii(:) jj(:) B(:)];

如果你不介意不同的订单(根据你的编辑),你可以更容易地做到:

[ii jj] = ndgrid(1:size(A,1),1:size(A,2));
R = [ii(:) jj(:) A(:)];

答案 2 :(得分:5)

除了使用meshgrid生成行/列索引外,您还可以使用find的所有三个输出,如下所示:

[II,JJ,AA]= find(A.'); %' note the transpose since you want to read across
M = [JJ II AA]
M =
            1            1         0.12
            1            2         0.23
            1            3         0.34
            2            1         0.45
            2            2         0.56
            2            3         0.67
            3            1         0.78
            3            2         0.89
            3            3          0.9

有限的申请,因为零丢失。令人讨厌,但正确的解决方法(感谢user664303):

B = A.'; v = B == 0; %' transpose to read across, otherwise work directly with A
[II, JJ, AA] = find(B + v);
M = [JJ II AA-v(:)];

毋庸置疑,我会推荐其他解决方案之一。 :)特别是,ndgrid是获取行的最自然的解决方案。

答案 3 :(得分:1)

我发现ndgrid是最自然的解决方案,但这是一种有趣的方式,可以使用奇怪的kronrepmat手动执行此操作:

M = [kron(1:size(A,2),ones(1,size(A,1))).' ...  %' row indexes
     repmat((1:size(A,1))',size(A,2),1) ...     %' col indexes
     reshape(A.',[],1)]                         %' matrix values, read across

简单调整读取,这在MATLAB中是很自然的:

M = [repmat((1:size(A,1))',size(A,2),1) ...     %' row indexes (still)
     kron(1:size(A,2),ones(1,size(A,1))).' ...  %' column indexes
     A(:)]                                      %  matrix values, read down

(也是因为我的第一个回答是淫秽的。)


我还发现kron是一个很好的工具,可以一次复制每个元素,而不是像repmat那样一次复制整个数组。例如:

>> 1:size(A,2)
ans =
     1     2     3
>> kron(1:size(A,2),ones(1,size(A,1)))
ans =
     1     1     1     2     2     2     3     3     3

更进一步,我们可以生成一个名为repel的新函数来复制数组的元素而不是整个数组:

>> repel = @(x,m,n) kron(x,ones(m,n));
>> repel(1:4,1,2)
ans =
     1     1     2     2     3     3     4     4
>> repel(1:3,2,2)
ans =
     1     1     2     2     3     3
     1     1     2     2     3     3