Search code examples
matlabcell-array

Extract data from a Cell Array using a vector and converting into an array


I have a cell array [5x1] which all cells are column vectors such as:

exInt =

    [46x1 double]
    [54x1 double]
    [40x1 double]
    [51x1 double]
    [ 9x1 double]

I need to have a vector (vec) containing the cells in extInt I need to extract and then I have to convert these into a single column array. Such as:

    vec = [1,3];
    Output = cell2mat(extInt{vec})

Output should become something an array [86x1 double].

The way I have coded I get:

Error using cell2mat
Too many input arguments.

If possible, I would like to have a solution not using a loop.


Solution

  • The best approach here is to use cat along with a comma-separted list created by {} indexing to yield the expected column vector. We specify the first dimension as the first argument since you have all column vectors and we want the output to also be a column vector.

    out = cat(1, extInt{vec})
    

    Given your input, cell2mat attempts to concatenate along the second dimension which will fail for your data since all of the data have different number of rows. This is why (in your example) you had to transpose the data prior to calling cell2mat.

    Update

    Here is a benchmark to compare execution times between the cat and cell2mat approaches.

    function benchit()
    
        nRows = linspace(10, 1000, 100);
    
        [times1, times2] = deal(zeros(size(nRows)));
    
        for k = 1:numel(nRows)
    
            rows = nRows(k);
    
            data = arrayfun(@(x)rand(randi([10, 50], 1), 1), 1:rows, 'uni', 0);
            vec = 1:2:numel(data);
    
            times1(k) = timeit(@()cat_method(data, vec));
    
            data = arrayfun(@(x)rand(randi([10, 50], 1), 1), 1:rows, 'uni', 0);
            vec = 1:2:numel(data);
    
            times2(k) = timeit(@()cell2mat_method(data, vec));
        end
    
        figure
    
        hplot(1) = plot(nRows, times1 * 1000, 'DisplayName', 'cat');
        hold on
        hplot(2) = plot(nRows, times2 * 1000, 'DisplayName', 'cell2mat');
    
        ylabel('Execution Times (ms)')
        xlabel('# of Cell Array Elements')
    
        legend(hplot)
    end
    
    function out = cat_method(data, vec)
        out = cat(1, data{vec});
    end
    
    function out = cell2mat_method(data, vec)
        out = cell2mat(data(vec)');
    end
    

    enter image description here

    The reason for the constant offset between the two is that cell2mat calls cat internally but adds some additional logic on top of it. If you just use cat directly, you circumvent that additional overhead.