7

In matlab I have a 4x5 cell array where each cell consists of an 121x1 vector.

What is the easiest way to create an 3-dim 4x5x121 matrix avoiding a 2-fold loop.

user1618022
  • 163
  • 1
  • 6

4 Answers4

7

One way (not necessarily the fastest)

%# convert all arrays in the cell array inCell to 1x1x121
permCell = cellfun(@(x)permute(x,[3,2,1]),inCell,'uniformOutput',false);

%# catenate
array = cell2mat(permCell);
Jonas
  • 74,690
  • 10
  • 137
  • 177
4

Suppose

A = cellfun(@(~)rand(121,1), cell(4,5), 'uniformoutput', false)

then normally I would say

cat(3, A{:})

but that would give a 121-by-1-by-20 array. For your case, an extra step is needed:

A = cellfun(@(x)permute(x,3,2,1), A, 'uniformoutput', false)
A = reshape([A{:}], size(A,1), size(A,2), size(A{1},3))

or, alternatively,

A = cellfun(@(x)permute(x,3,2,1), A, 'uniformoutput', false)
A = cell2mat(A);

although

>> start = tic;
>> for ii = 1:1e3
>>     B1 = reshape([A{:}], size(A,1), size(A,2), size(A{1},3)); end
>> time1 = toc(start);
>> 
>> start = tic;
>> for ii = 1:1e3
>>     B2 = cell2mat(A); end
>> time2 = toc(start);
>> 
>> time2/time1
ans = 
     4.964318459657702e+00

so the command cell2mat is almost 5 times slower than the reshape of the expansion. Use whichever seems best suited for your case.

Rody Oldenhuis
  • 37,726
  • 7
  • 50
  • 96
1

The answers by Jonas and Rody are of course fine. A small performance refinement is to reshape your vectors in the cells rather than permute them:

permCell = cellfun(@(x)reshape(x,[1 1 numel(x)]), inCell, 'uni',false);
A = reshape([permCell{:}], [size(inCell) numel(inCell{1,1})]);

And by far the fastest, if you can relax the requirements about the output dimensions, is simply concatenating the cell vectors and reshaping

A = reshape([inCell{:}], [numel(inCell{1,1}) size(inCell)]);

which yields a [121 x 4 x 5] matrix.

Rody Oldenhuis
  • 37,726
  • 7
  • 50
  • 96
angainor
  • 11,760
  • 2
  • 36
  • 56
  • Which is **not** faster than `cat(3, A{:})` (well *you* said the requirements on output dimensions could be relaxed :) – Rody Oldenhuis Oct 22 '12 at 10:24
  • @RodyOldenhuis oh, ok. I see you refer to your answer. Sorry. I missed that part :) But you also need a reshape then. `size(cat(3, c{:})) ans = 121 1 20` – angainor Oct 22 '12 at 10:33
0

How about this, avoiding cellfun:

 output=permute(cell2mat(permute(input,[3 1 2])),[2 3 1]);

Haven't compared speed to the other suggestions though.

tmpearce
  • 12,523
  • 4
  • 42
  • 60