Reputation: 163
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.
Upvotes: 7
Views: 3003
Reputation: 12693
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.
Upvotes: 0
Reputation: 74930
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);
Upvotes: 7
Reputation: 11810
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.
Upvotes: 1
Reputation: 38032
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.
Upvotes: 4