AnnaSchumann
AnnaSchumann

Reputation: 1271

Converting cell array of matrices to a 2D matrix

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?

Upvotes: 1

Views: 177

Answers (3)

Divakar
Divakar

Reputation: 221684

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

Upvotes: 1

m.s.
m.s.

Reputation: 16354

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

Upvotes: 0

Hoki
Hoki

Reputation: 11812

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]

Upvotes: 1

Related Questions