2

I am trying to add vertically the lists of a database like DB (see below) contained in a cell.

DB={ {[11 12]}  {[13 14]} {[15 16]} {[17 18]} {[19 20]};

    {[21 22]} {[23 24]} {[25 26]} {[27 28]} {[29 30]};

    {[31 32]} {[33 34]} {[35 36]} {[37 38]} {[39 40]}}

I would like to get:

 [33 36]  [69 72] [75 78] [81 44] [ 87 90 ]

I tried with a 'for' loop (see below) ... but taking too much time.

How could I do this with the minimum of 'for' loops or even better, without any loop?

Thank you very much for your attention.

sum=[ ]
for j=1:5
    sumi=0
    for i=1:3
    sumi=sumi+ c2{i,j}{1}
    end
    sum=[sum sumi]
end
5
  • 1
    (1) Do you really need a cell array of cell arrays? It would be much easier if you stored the numbers in a numeric 2D or 3D array, or if you convert into that. (2) Is the result correct? For example, how is 33 obtained? (3) What type of array do you need the result to be? What you show is 5 separate arrays. Commented Jan 21 at 19:19
  • 1
    The worst part of your code is the line sum=[sum sumi], which creates a new array and copies the data into it. You should never do that inside a loop. Read about preallocation: mathworks.com/help/matlab/matlab_prog/preallocating-arrays.html Commented Jan 21 at 20:15
  • 1
    The other bad thing is the data format. If I were you I’d rethink how you store the data. An array has overhead (memory wise). Storing an array by itself inside a cell array doubles the overhead. Also, indexing is relatively expensive in MATLAB. Consider storing all your data in a single array (make it multi-dimensional if appropriate). Commented Jan 21 at 20:18
  • 2
    avoid using sum as a variable name, you're shadowing the in-built function which can cause unexpected errors Commented Jan 22 at 8:16
  • 2
    For such a small example it's hard to definitively suggest what the fastest approach might be, presumably if this is too slow then your real input is significantly larger? Commented Jan 22 at 9:11

3 Answers 3

5

Based on your code, you can achieve the same result with

result = sum(cell2mat(cellfun(@(x) x, DB)), 1);

or better (thanks to @Wolfie)

result = sum(cell2mat(reshape([DB{:}], size(DB, 1), [])), 1);

This converts your cell array of cell arrays into a numerical 2D array, and then sums along the vertical dimension. However, this is not likely to be much faster than your current code.

The issue with your approach is not the code, but the data type. If possible, you should define your DB variable directly as a numerical 2D array. That way the code would be simpler and faster: result = sum(DB, 1);. Normally, cell arrays in Matlab are only used if the contents are not homogenous in size or in type.

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you for the comment Luis mendo.. Nevertheless.. I suppose something went wrong..I got this error message: DB = 3x5 cell array {1x1 cell} ... Index in position 1 exceeds array bounds. Index must not exceed 1. Error in untitled (line 8) result = sum(cell2mat(cellfun(@(x) x, DB)), 1) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (I didn't check the time that it take yet). Thank you for your reply. JJVVE
@jeanjacquesvivde It works with DB as defined in your question; see here
In a quick test I think using cellfun is slowing you down here, you could do something similar de-nesting with {:} and a reshape e.g. sum(cell2mat(reshape([DB{:}],size(DB,1),[])), 1)
@Wolfie Good idea, thanks! Edited into the answer
3

One slightly faster approach is to reduce to a single loop, and pre-allocate the output:

n = 2;
s = NaN( 1, n*size(DB,2) );
for ii = 1:size(DB,2)
    col = vertcat(DB{:,ii});
    s(n*(ii-1)+1:n*ii) = sum( vertcat(col{:}) );
end

Note that n here is the number of elements within each cell, which in your example was 2.

Comments

2

Maybe you can try

table2cell(varfun(@(x) sum(cell2mat(x),1),cell2table(DB)))

and you will obtain the result presented like

  1×5 cell array

    {[63 66]}    {[69 72]}    {[75 78]}    {[81 84]}    {[87 90]}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.