2015-08-30 259 views
5

我有一个3D单元阵列,指定为A{s,i,h},用作我的脚本的嵌套循环部分期间的大量数值数据的存储。一些细胞的条目为空白[ ]的,其余包含数字 - 无论是单数或在阵列(1×10双等):从三维单元阵列转换为一组二维矩阵

enter image description here

欲此单元阵列转换成一组的二维矩阵。

具体而言,每个值h(h始终等于1:3)的一个单独矩阵以及每个值为s的每个值的一列。每列将包含所有数字数据的组合 - 它不需要由i分隔。

我该怎么办?我通常与3D-单元阵列处理中使用这样的这种形式,以产生单独的矩阵(一个用于H的每值):

lens = sum(cellfun('length',reshape(A,[],size(A,3))),1); 
max_length = max(lens); 
mat = zeros(max_length,numel(lens)); 
mask = bsxfun(@le,[1:max_length]',lens); 
mat(mask) = [A{:}]; 
mat(mat==0) = NaN; 
mat = sort(mat*100); 
Matrix1 = mat(~isnan(mat(:,1)),1); 
Matrix2 = mat(~isnan(mat(:,2)),2); 
Matrix3 = mat(~isnan(mat(:,3)),3); 

然而,在这种情况下,每个矩阵只有一列。我无法为每个输出矩阵添加多列。

+0

才可保证您的输出矩阵的所有列将具有相同的长度?或者你需要定义一个填充值? –

+0

确保它们的长度不会相同 - 因此需要填充。 – AnnaSchumann

+0

另外,你的分组索引是'h'还是'm'还是'i'和'm'?请编辑答案,正如它说'h'和'm',然后'i'和'm' –

回答

2

1。结果在矩阵的单元阵列(如需要)的形式

这里的一个可能的方法。我不得不使用一个for循环。但是,如果您接受3D阵列结果而不是2D阵列单元阵列,则可以轻松避免循环。请参阅答案的第二部分。

如果您按照代码中的注释并检查每个步骤的结果,可以直接看到它的工作原理。

%// Example data 
A(:,:,1) = { 1:2, 3:5, 6:9; 10 11:12 13:15 }; 
A(:,:,2) = { 16:18, 19:22, 23; 24:28, [], 29:30 }; 

%// Let's go 
[S, I, H] = size(A); 
B = permute(A, [2 1 3]); %// permute rows and columns 
B = squeeze(mat2cell(B, I, ones(1, S), ones(1, H))); %// group each col of B into a cell... 
B = cellfun(@(x) [x{:}], B, 'uniformoutput', false); %// ...containing a single vector 
t = cellfun(@numel, B); %// lengths of all columns of result 
result = cell(1,H); %// preallocate 
for h = 1:H 
    mask = bsxfun(@le, (1:max(t(:,h))), t(:,h)).'; %'// values of result{h} to be used 
    result{h} = NaN(size(mask)); %// unused values will be NaN 
    result{h}(mask) = [B{:,h}]; %// fill values for matrix result{h} 
end 

结果在这个例子中:

A{1,1,1} = 
    1  2 
A{2,1,1} = 
    10 
A{1,2,1} = 
    3  4  5 
A{2,2,1} = 
    11 12 
A{1,3,1} = 
    6  7  8  9 
A{2,3,1} = 
    13 14 15 
A{1,1,2} = 
    16 17 18 
A{2,1,2} = 
    24 25 26 27 28 
A{1,2,2} = 
    19 20 21 22 
A{2,2,2} = 
    [] 
A{1,3,2} = 
    23 
A{2,3,2} = 
    29 30 

result{1} = 
    1 10 
    2 11 
    3 12 
    4 13 
    5 14 
    6 15 
    7 NaN 
    8 NaN 
    9 NaN 
result{2} = 
    16 24 
    17 25 
    18 26 
    19 27 
    20 28 
    21 29 
    22 30 
    23 NaN 

2.结果在3D阵列

的形式如上面所指出的,使用3D数组来存储结果允许避免环路。在下面的代码中,最后三行替换了答案第一部分中使用的循环。其余的代码是一样的。

%// Example data 
A(:,:,1) = { 1:2, 3:5, 6:9; 10 11:12 13:15 }; 
A(:,:,2) = { 16:18, 19:22, 23; 24:28, [], 29:30 }; 

%// Let's go 
[S, I, H] = size(A); 
B = permute(A, [2 1 3]); %// permute rows and columns 
B = squeeze(mat2cell(B, I, ones(1, S), ones(1, H))); %// group each col of B into a cell... 
B = cellfun(@(x) [x{:}], B, 'uniformoutput', false); %// ...containing a single vector 
t = cellfun(@numel, B); %// lengths of all columns of result 
mask = bsxfun(@le, (1:max(t(:))).', permute(t, [3 1 2])); %'// values of result to be used 
result = NaN(size(mask)); %// unused values will be NaN 
result(mask) = [B{:}]; %// fill values 

这给(与第一部分的结果比较):

>> result 
result(:,:,1) = 
    1 10 
    2 11 
    3 12 
    4 13 
    5 14 
    6 15 
    7 NaN 
    8 NaN 
    9 NaN 
result(:,:,2) = 
    16 24 
    17 25 
    18 26 
    19 27 
    20 28 
    21 29 
    22 30 
    23 NaN 
    NaN NaN 
0

暴力方法:

[num_s, num_i, num_h] = size(A); 
cellofmat = cell(num_h,1); 
for matrix = 1:num_h 
    sizemat = max(cellfun(@numel, A(:,1,matrix))); 
    cellofmat{matrix} = nan(sizemat, num_s); 
    for column = 1:num_s 
     lengthcol = length(A{column, 1, matrix}); 
     cellofmat{matrix}(1:lengthcol, column) = A{column, 1,matrix}; 
    end 
end 
Matrix1 = cellofmat{1}; 
Matrix2 = cellofmat{2}; 
Matrix3 = cellofmat{3}; 

我不知道你的实际结构是什么样子,但这个工程的A是使用以下步骤设置。

A = cell(20,1,3); 
for x = 1:3 
    for y = 1:20 
     len = ceil(rand(1,1) * 10); 
     A{y,1,x} = rand(len, 1); 
    end 
end 
+0

被编辑为修复内部循环索引的错误。以前我使用'num_h'而不是'matrix',因此所有3个输出矩阵都是相同的。 – Matt

相关问题