1
votes

I've got a simple 2D cell array that contains data in the form of:

enter image description here

What is the simplest way to be able to use cat/cell2mat when each column can be of an unequal length? Is there a way to replace [] entries with 0?

EDIT:

Desired output would be a matrix with the same number of columns. For the example shown above, the rows in the first column would contain:

42
58
81
19
84
16
40
60
40
36

and so on while the rows of the second column would contain:

57
29
14
5
9
69
17
84
12
4

and so on.

EDIT2:

Adding zeroes would look something like this:

enter image description here

3
what is the result you want to get? do you want 6 matrices (rows) each containing two columns with an unknown number of elements? Why do you need it at all? Because right now you have all your data nicely put together and you can easily loop/address each data - The Minion
Can you describe the desired output? Im guessing it's a numerical array but of what size? - danny
and are those entries in each row of cell array always one dimensional? (I mean is each a column vector?) - Autonomous
A matrix can't have two columns with unequal lengths - Luis Mendo
@ The Minion - see my edit. I need to be able to tally the instances of each recurring number for each column of the cell array. For example - 100 occurs 3 times in the first cell array column. I thought the best would to do this would be to convert it into a matrix and then use histc like normal. - AnnaSchumann

3 Answers

4
votes

Maybe this is what you want. Zeros are added at the end.

c = {[1;2] [10; 20; 30]; [3;4;5] [40]; [6; 7] []}; %// example
c1 = vertcat(c{:,1});
c2 = vertcat(c{:,2});
n1 = numel(c1);
n2 = numel(c2);
result = zeros(max(n1,n2),2);
result(1:n1,1) = c1;
result(1:n2,2) = c2;

In this example:

>> celldisp(c)
c{1,1} =
     1
     2
c{2,1} =
     3
     4
     5
c{3,1} =
     6
     7
c{1,2} =
    10
    20
    30
c{2,2} =
    40
c{3,2} =
     []
>> result
result =
     1    10
     2    20
     3    30
     4    40
     5     0
     6     0
     7     0
1
votes

This solution proposes an almost vectorized approach to solve the stated problem and also makes it a generic one for any number of columns in an input cell array. This is categorized as "almost-vectorized" one because it uses cellfun('length'..) (if you look at the code) and AFAIK cellfun is basically a wrapper to a for-loop. But in this case, cellfun('length'..) is very lightweight and rest of the code is vectorized and that's why the term "almost-vectorized".

Code -

%// 3 column sized input cell array
c = {[1;2] [10; 20; 30] [3;8;42]; [3;4;5] [40] [3]; [6; 7] [] [5;9;11;32]} 

lens = sum(cellfun('length',c),1)
out = zeros(max(lens),numel(lens))
out(bsxfun(@le,[1:max(lens)]',lens)) = vertcat(c{:})

Output -

>> c
c = 
    [2x1 double]    [3x1 double]    [3x1 double]
    [3x1 double]    [        40]    [         3]
    [2x1 double]              []    [4x1 double]
>> out
out =
     1    10     3
     2    20     8
     3    30    42
     4    40     3
     5     0     5
     6     0     9
     7     0    11
     0     0    32
0
votes

I would urge you to take a look at cellfun. My solution below would work really well, were it not for the 'UniformOutput', false-part. This is only necessary because some cells in my example are empty matrices, on which histc behaves differently.

cellarray = cell(3,2);
cellarray(:,1)= {[3, 2, 1]; [12, 3, 4, 6]; []};

edges = 1:13; % If you do not know the range of values, find them using cellfun(min, cellarray), and max
x = cellfun(@(x)histc(x, edges), cellarray, 'UniformOutput', false)