将单元格数组的单元格数组转换为矩阵的矩阵。

8
我可以将一个矩阵的单元数组转化为矩阵:
>> C={[1,1]; [2,2]; [3,3]};
>> cell2mat(C)
ans =
     1     1
     2     2
     3     3

这是没问题的。但是,我想将一个包含其他单元格数组的单元格数组转换为矩阵:

>> C={{1,1}; {2,2}; {3,3}};    
>> cell2mat(C)
Error using cell2mat (line 53)
Cannot support cell arrays containing cell arrays or objects.

因此,期望的输出是:

>> mycell2mat({{1,1}; {2,2}; {3,3}})
ans =
     1     1
     2     2
     3     3

如何做这个?

编辑:

我也想对多维数组进行同样的操作:

>> mycell2mat({{1,1;1,1}; {2,2;2,2}; {3,3;3,3}})
ans(:,:,1) =

     1     1
     1     1

ans(:,:,2) =

     2     2
     2     2

ans(:,:,3) =

     3     3
     3     3
5个回答

10

说实话,我从不喜欢cell2mat因为它运行较慢,所以我想出了一种使用逗号分隔列表的替代方案!

将向量的单元数组转换

这很简单,只需使用冒号运算符并竖直拼接所有向量

C = {[1,1]; [2,2]; [3,3]};
A = vertcat(C{:})

因此我们得到:

A =
    1   1
    2   2
    3   3

将一个单元格数组转换为矩阵

这是有点棘手的。由于它是一个单元格数组,我们需要使用冒号和 horzcat 两次来获取所有元素的向量,然后将其 reshape 成所需的矩阵。

C = {{1,1}; {2,2}; {3,3}};
V = [size(C{1}), 1]; V(find(V == 1, 1)) = numel(C);
A = reshape([horzcat(C{:}){:}], V)

于是我们得到:

A =
    1   1
    2   2
    3   3

通过对V进行操作,可以确保A正确地重新形状,而不必显式指定输出维度(可惜的是,我没有找到一种一行代码的方法)。这也适用于多维单元数组:

C = {{1, 1; 1, 1}; {2, 2; 2, 2}; {3, 3; 3, 3}};
V = [size(C{1}), 1]; V(find(V == 1, 1)) = numel(C);
A = reshape([horzcat(C{:}){:}], V)

A(:,:,1) = 
    1   1
    1   1

A(:,:,2) =   
    2   2
    2   2

A(:,:,3) =    
    3   3
    3   3

附言

我认为最后一个示例的正确结果应该是6×2矩阵,而不是2×2×3矩阵。不过,这不是您所请求的内容,所以这超出了讨论范围。


5
这应该可以解决问题:
cellOfCells = {{1,1}; {2,2}; {3,3}};
cell2mat(cellfun(@cell2mat, cellOfCells, 'UniformOutput', false))

编辑:

我认为保持简单很重要,但是享受乐趣同样重要 :) 因此 - 这里有一个一行代码,可以解决问题(并且可以轻松地推广到任何大小):

a = {{1,1;1,1}; {2,2;2,2}; {3,3;3,3}}
reshape(cell2mat(cellfun(@cell2mat,a, 'UniformOutput', false))', 2, 2, 3)

谢谢Ronnyle,你所提供的代码可以用于我给出的一维数组,非常有效。但是,我需要将同样的方法应用在多维数组上,你能否进一步改进你的答案? - mmdemirbas

3
保持简单
c = {{1,1;1,1}; {2,2;2,2}; {3,3;3,3}};
z = zeros([size(c{1}) size(c,1)]);

for i=1:size(c,1)
    z(:,:,i)=cell2mat(c{i});
end

提供

EDU>> z    
z(:,:,1) =

     1     1
     1     1

z(:,:,2) =

     2     2
     2     2    

z(:,:,3) =

     3     3
     3     3

2

好的,这个问题已经存在很长时间了,但也许我的答案可以帮助其他读者或搜索者。
我认为最好的解决方案几乎是由Eitan T提出的想法,但可以在不改变形状的情况下实现。对于我来说

C={{1,1;1,1};{2,2;2,2};{3,3;3,3}};
A=cell2mat(cat(3,C{:}))

做到了被要求的事情 - 因此回答为
A(:,:,1) =
     1     1
     1     1
A(:,:,2) =
     2     2
     2     2
A(:,:,3) =
     3     3
     3     3

希望这有所帮助。

1
我遇到了同样的错误,我只是在cell2mat中注释掉了返回错误的行,然后一切都正常了。
需要注释掉的行(51-53):(您可以使用dbstop if error找到它们)
如果cisobj || ciscell error(message('MATLAB:cell2mat:UnsupportedCellContent')); end
我认为更改matlab函数并不是一个好主意,我自己的解决方案也相当可耻,但它有效。

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