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

3

我该如何转换一个矩阵:

[ 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个回答

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
为了简洁起见,您可以使用以下代码:ind2sub(size(A), 1:numel(A)) - Notlikethat
他说行的排列顺序不重要,所以这样做也没问题。这些行本质上仍然是相同的。(顺便提一下,这是指您的注释) - scenia

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(:)];

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 是获得行、列索引最自然的解决方案。

哦,但是零... 嗯嗯 - chappjc
一种不太优雅的解决方案来处理零的情况:先加上 min(A(:))+1,然后再减去它。 - Luis Mendo
1
错误修复且不会失去准确性:B = A.'; v = B == 0; [II, JJ, AA] = find(B + v); M = [JJ II AA-v(:)]; - user664303
@user664303:感谢您的建议。即使是我自己也不会使用这个“find”方法,但是嘿……它确实可以工作。 - chappjc

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接