1
votes

I have a cell-array of matrices (A):

enter image description here

And want to convert this into a singular 2D matrix by padding each column to an equal length (in this case - 197) and reshaping it in a specific manner such A{1,1} occupies the first three columns of the output matrix, A{1,2} occupies the next three and so forth.

The latter can likely be achieved via horzcat however I am not sure how to pad a cell array when each cell contains a matrix - rather than a vector, where i'd normally use something along the lines of:

Lmax = max(max(cell2mat(cellfun(@numel,A,'un',0)))) ;
b = cellfun(@(c)[c(:);NaN(Lmax-numel(c),1)],A,'uniformoutput',0);

Padding with either NaNs or 0's is acceptable.

How can I do this?

3
are all your matrix inside the cell array with 3 columns exactly (only the number of line differ) ? - Hoki
@Hoki Yes - always three columns, however the number of cells can be variable. - AnnaSchumann
@m.s Updated, I incorrectly labelled it. - AnnaSchumann

3 Answers

1
votes

This is just an extension of the previous answer to your question Pad cell array with whitespace and rearrange.

The method is exactly the same, the only trick now you have matrices instead of vectors is to use size instead of numel. It becomes:

%// sample data
A = { randi(10,5,3) , randi(10,8,3) ; randi(10,6,3) , randi(10,3,3) } 
A = 
    [5x3 double]    [8x3 double]
    [6x3 double]    [3x3 double]

Using the same method (replacing numel with size(...,1) to get the number of lines right:

%%
nCol = 3 %// number of columns for the padding lines

%// get the length of the longest vector
Lmax = max(max( cellfun('size',A,1) )) ;
%// pad columns with necessary number of NaN
b = cellfun( @(c) [c ; NaN(Lmax-size(c,1),nCol)], A ,'un',0 ) ;
%// reshape if you want your cell array in columns
b = b(:).' 

>> b
b = 
    [8x3 double]    [8x3 double]    [8x3 double]    [8x3 double]
1
votes

Almost vectorized approach with bsxfun's masking capability -

%// Set parameters
nrows = cellfun('size',A,1)
ncols = size(A{1,1},2)
maxr = max(nrows)

%// Get mask
mask = bsxfun(@le,[1:maxr]',nrows)  %//'
out = zeros(maxr*numel(nrows),ncols)
out(mask(:),:) = vertcat(A{:})

%// Final output
b = reshape(permute(reshape(out,maxr,numel(nrows),[]),[1 3 2]),maxr,[])

Sample run -

>> A{1,1}
ans =
     5     6     2
     6     9     1
     4     7     1
     4     4     2
     5     8     3
>> A{1,2}
ans =
     3     5     2
     1     1     6
>> A{1,3}
ans =
     8     5     5
     9     5     1
     6     3     8
     9     4     1
>> A{1,4}
ans =
     4     8     4
>> b
b =
     5     6     2     3     5     2     8     5     5     4     8     4
     6     9     1     1     1     6     9     5     1     0     0     0
     4     7     1     0     0     0     6     3     8     0     0     0
     4     4     2     0     0     0     9     4     1     0     0     0
     5     8     3     0     0     0     0     0     0     0     0     0
0
votes

Instead of numel you need to use size, then the following modification of your code works:

Lmax = max(cellfun('size',A,1));
b = cellfun(@(c)[c;NaN(Lmax-size(c,1),3)],A,'uniformoutput',0);

c = horzcat(b{:}); % this holds your final matrix