2

Assume Q is a matrix which has 3 cells and in each cell it has 2 other cells, means:

Q={ { [] [] } ; { [] [] }; { [] [] } }

Moreover, if we have "a" and "b" which they have 3 member each, and we would like to place

"a(1,1)" into "Q{1}{1}",

"b(1,1)" into "Q{1}{2}",

"a(2,1)" into "Q{2}{1}",

"b(2,1)" into "Q{2}{2}",

"a(3,1)" into "Q{3}{1}",

"b(3,1)" into "Q{3}{2}",

For example, if

a = [2; 3; 4];
b = [1; 5; 8] 

Then Q should be like

Q={{2 1}; 
   {3 5}; 
   {4 8}}

Please note that we need a vectorized code and not a for-loop code as I already have the latter one, as shown next -

for i=1:size(Q,2)

     Q{i}{1}=a(i,:)
     Q{i}{2}=b(i,:)

end

Thanks.

Divakar
  • 218,885
  • 19
  • 262
  • 358
Iman
  • 412
  • 4
  • 18
  • And what's the problem with your loop? – Dan Jul 16 '14 at 09:25
  • I cleaned up your `Q` (keeping it structurally identical to how you had it) and it contradicts your loop which has cells in cells. Is there a reason to have the inner matrices as cells? i.e. can those scalars ever not be scalars? And also why not just `Q = [a,b]` and forget about cells? – Dan Jul 16 '14 at 09:28
  • How about this - `Q = mat2cell([a b].',2,ones(1,numel(a))).'`? – Divakar Jul 16 '14 at 09:44
  • @Dan There is a reason to put each member inside of a sub-cell matrix into each super-cell as I just simplified the Q, a, b matrices. Actually, Q and other matrices in my code have billions of numbers and each sub-cell represent a different characteristic. Moreover, I would like to write it in line instead of loop as it can be very expensive and time consuming for such a huge data. BTW, thanks for your attention. – Iman Jul 16 '14 at 10:05
  • @Divakar Many thanks. It looks very good. I was wondering if you could let me know how I can have each **"a"** & **"b"** members into separated cells. For example: `Q={{2}{1};{3}{5};{4}{8}}` – Iman Jul 16 '14 at 10:08
  • @Iman Maybe this - `mat2cell([a b].',[1 1],ones(1,numel(a))).'` – Divakar Jul 16 '14 at 10:10
  • @Iman Have you tried preallocating `Q`? – Dan Jul 16 '14 at 10:12
  • @Divakar You're amazing man! That's the one! If you could write your solution as a answer then I can mark it as final answer. – Iman Jul 16 '14 at 10:13
  • @Dan Yes, I did. But still this line should be faster than a loop. Am not 100% sure, I will apply it on my data and let you know. Thanks again. – Iman Jul 16 '14 at 10:15
  • 1
    @Dan I applied it for **100000** numbers. The loop were faster that the line: `a=(1:100000)'; b=(1:100000)';` `tic Q=cell(size(a,1),1); for i=1:size(Q,1) Q{i}{1}=a(i,:); Q{i}{2}=b(i,:); end toc Elapsed time is 0.372703 seconds.` `tic Q=mat2cell(mat2cell([a b].',[1 1],ones(1,numel(a))).',ones(1,size(a,1)).'); toc Elapsed time is 0.717828 seconds.` – Iman Jul 16 '14 at 13:04
  • @Iman Check out the edits in my solution, that includes benchmarking. – Divakar Jul 17 '14 at 06:24

1 Answers1

2

Code

Q = mat2cell(num2cell([a b]),ones(1,numel(a)),2)

Example

Code with input and output display

a = [2; 3; 4]; %// Inputs
b = [1; 5; 8];

Q = mat2cell(num2cell([a b]),ones(1,numel(a)),2); %// Output

celldisp(Q) %// Display results

Output on code run

Q{1}{1} =
     2
Q{1}{2} =
     1
Q{2}{1} =
     3
Q{2}{2} =
     5
Q{3}{1} =
     4
Q{3}{2} =
     8

Benchmarking

Function for loop method

function out = loop1(a,b)

out = cell(size(a,1),1); 
for i=1:size(out,1) 
    out{i}{1}=a(i,:); 
    out{i}{2}=b(i,:);
end

return;

Function for vectorized method

function out = vec1(a,b)

out = mat2cell(num2cell([a b]),ones(1,numel(a)),2);

return;

Benchmarking Code

N_arr = [50 100 200 500 1000 2000 5000 10000 50000]; %// array elements for N

timeall = zeros(2,numel(N_arr));
for k1 = 1:numel(N_arr)
    
    N = N_arr(k1);
    a = randi(9,N,1);
    b = randi(9,N,1);
    
    f = @() loop1(a,b);
    timeall(1,k1) = timeit(f);
    clear f
    
    f = @() vec1(a,b);
    timeall(2,k1) = timeit(f);
    clear f
end

%// Graphical display of benchmark results
figure,
hold on
plot(N_arr,timeall(1,:),'-ro')
plot(N_arr,timeall(2,:),'-kx')
legend('Loop Method','Vectorized Method')
xlabel('Datasize (N) ->'),ylabel('Time(sec) ->')

Results

enter image description here

Conclusions

Looks like vectorized method is the way to go, as it's showing almost double the performance (in terms of runtime) as compared to the loop approach across a wide range of datasizes.

Community
  • 1
  • 1
Divakar
  • 218,885
  • 19
  • 262
  • 358
  • This look great. I was just wondering how we can put each array into a cell? I mean instead of `Q = {{2}{1};{3}{5};{4}{8}}` it comes into `Q = {{{2}{1}};{{3}{5}};{{4}{8}}}` – Iman Jul 16 '14 at 10:51
  • @Iman I am not sure how would you obtain or at least "picturise" - `Q = {{{2}{1}};{{3}{5}};{{4}{8}}}`? At least explain what is it? – Divakar Jul 16 '14 at 10:54
  • Maybe further explanation would be helpful. I need **"Q"** in form of `Q={ {{}{}}; {{}{}}; {{}{}} }`. That's why it is named as a **multilayer** cell-matrix. It supposed to have 2 different depths. – Iman Jul 16 '14 at 11:04
  • @Iman See if this works - `mat2cell(mat2cell([a b],ones(1,numel(a)),[1 1]),[1 1 1],2)`? – Divakar Jul 16 '14 at 11:12
  • Exactly! That's what I've just came to write. `Q=mat2cell(mat2cell([a b].',[1 1],ones(1,numel(a))).',ones(1,size(Q,1)).')` Thanks a million ;) – Iman Jul 16 '14 at 11:17
  • Yes, That is great. I appreciate it. I have just updated your answer if it is OK for you. – Iman Jul 16 '14 at 11:21