1

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?

AnnaSchumann
  • 1,261
  • 10
  • 22

3 Answers3

1

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]
Community
  • 1
  • 1
Hoki
  • 11,637
  • 1
  • 24
  • 43
1

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
Divakar
  • 218,885
  • 19
  • 262
  • 358
  • What makes this almost vectorised as opposed to fully vectorised? – AnnaSchumann Sep 10 '15 at 10:43
  • @AnnaSchumann Use of `cellfun('size',A,1)` as `cellfun` isn't really a vectorized usage, but that should be very light on performance as it's not doing any computation with it. I was just trying to be technically correct there :) – Divakar Sep 10 '15 at 10:44
0

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
m.s.
  • 16,063
  • 7
  • 53
  • 88
  • `length` is very dangerous. In this case it should be all right but if you **know** you have to get the number of **lines**, use `size(A,1)` as they could be no indetermination this way. – Hoki Sep 10 '15 at 10:02
  • 2
    Or use the in-built `cellfun('size',A,1)`, should be faster. – Divakar Sep 10 '15 at 10:03
  • @Divakar, thanks ... changed it too, I didn't know we could use this syntax. – Hoki Sep 10 '15 at 10:09