Search code examples
matlabmatrixmatlab-figure

Matlab: Plot non-equal matrices in a cell array without a loop


Knowing that:

There are a lot of discussion about plotting equal sized matrices in a cell array and it is quite easy to do without a loop.

For example, to plot the 2-by-2 matrices in mycell:

mycell = {[1 1; 2 1], [1 1; 3 1], [1 1; 4 1]};

We can use cellfun to add a row of NaN at the bottom of each matrix and then convert the cell to a matrix:

mycellnaned = cellfun(@(x) {[x;nan(1,2)]}, mycell);
mymat = cell2mat(mycellnaned');

mymat looks like:

     1   1   1   1   1 
     2   1   3   1   4 
    NaN NaN NaN NaN NaN

Then we can plot it easily:

mymatx = mymat(:,1:2:end);
mymaty = mymat(:,2:2:end);
figure;
plot(mymatx, mymaty,'+-');

The problem:

The problem is now, how do I do something similar with a cell containing non-equal matrices? Such as:

mycell = {
    [1:2; ones(1,2)]';
    [1:4; ones(1,4)*2]';
    [1:6; ones(1,6)*3]';
    [1:8; ones(1,8)*4]';
    [1:10; ones(1,10)*5]';
    [1:12; ones(1,12)*6]';
    };

mycell = repmat(mycell,1000,1);

I would not be able to convert them into one matrix like I did before. I could use a loop, as suggested in this answer, but it would be very inefficient if the cell contains thousands of matrices.

Therefore, I'm looking for a more efficient way of plotting non-equal sized matrices in a cell array.

Note that different colours should be used for different matrices in the figure.


Solution

  • Well, while I was writing the question, I figured it out...

    I'd like to keep the question open since there might be better solutions.

    For everyone else's reference, the solution is simple: add NaN to make the matrices equal sized:

    % find out the maximum length of all matrices in the array
    cellLengthMax = max(cellfun('length', mycell));
    
    % fill the matrices so they are equal in size.
    mycellfilled = cellfun(@(x) {[
        x
        nan(cellLengthMax-size(x,1), 2)
        nan(1, 2)
        ]}, mycell);
    

    Then convert to a matrix and plot:

    mymat = cell2mat(mycellfilled');
    mymatx = mymat(:,1:2:end);
    mymaty = mymat(:,2:2:end);
    
    figure;
    plot(mymatx, mymaty,'+-');
    

    mymat looks like:

         1     1     1     2     1     3     1     4     1     5     1     6
         2     1     2     2     2     3     2     4     2     5     2     6
       NaN   NaN     3     2     3     3     3     4     3     5     3     6
       NaN   NaN     4     2     4     3     4     4     4     5     4     6
       NaN   NaN   NaN   NaN     5     3     5     4     5     5     5     6
       NaN   NaN   NaN   NaN     6     3     6     4     6     5     6     6
       NaN   NaN   NaN   NaN   NaN   NaN     7     4     7     5     7     6
       NaN   NaN   NaN   NaN   NaN   NaN     8     4     8     5     8     6
       NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN     9     5     9     6
       NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN    10     5    10     6
       NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN    11     6
       NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN    12     6
       NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN   NaN
    

    enter image description here

    Update:

    Time cost for plotting 6000 matrices:

    using the solution proposed here: 1.183546 seconds.

    using a loop: 3.450423 seconds.

    Still not very satisfactory. I really wish to reduce the time to 0.1 seconds, because I'm trying to design an interactive UI, where the user can change a few parameters and the result get plotted instantly.

    I don't want to reduce the resolution of the figure.

    Update:

    I did a profiler and it seems the 99% of the time is wasted on plot(mymatx, mymaty,'+-');. So the conclusion is, there is probably no other way to fasten this.