0

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.

3
  • What's the question? Doesn't this code work? If not, please list why not. Commented Sep 6, 2016 at 12:12
  • I'm sorry, I've edited the question. Commented Sep 6, 2016 at 12:16
  • Try cellfun Commented Sep 6, 2016 at 12:20

4 Answers 4

4

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.

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

Comments

3

You have a small error in your code

Change

Output = cell2mat(extInt{vec});

to

Output = cell2mat(extInt(vec));

For cells, both brackets and parentheses can be used to get information. You can read some more about it here, but to summarize:

  • Use curly braces {} for setting or getting the contents of cell arrays.
  • Use parentheses () for indexing into a cell array to collect a subset of cells together in another cell array.

In your example, using brackets with index vector vec will produce 2 separate outputs (I've made a shorter version of extInt below)

extInt = {[1],[2 3],[4 5 6]};
extInt{vec}
ans =
     1
ans =
     4     5     6

As this is 2 separate outputs, it will also be 2 separate input to the function cell2mat. As this function only takes one input you get an error.

One alternative is in your own solution. Take the two outputs and place them inside a new (unnamed) cell

{extInt{vec}}
ans = 
    [1]    [1x3 double]

Now, this (single) result goes into cell2mat without a problem. (Note though that you might need to transpose your result before depending on if you have column or row vectors in your cell. The size vector (or matrix) to combine need to match/align.)

Another way as to use parentheses (as above in my solution). Here a subset of the original cell is return. Therefore it goes directly into the cell2matfunction.

extInt(vec)
ans = 
    [1]    [1x3 double]

3 Comments

this works too.I thought cell arrays could only use {}
@ArturCastiel {} returns the contents of the cell array elements and () returns a subset of the cell array as a cell array
Indeed, I'll update my answer with some more information
0

I have been messing around and I got this working by converting this entry into a new cell array and transposing it so the dimensions remained equivalent for the concatenating process

Output = cell2mat({extInt{vec}}')

1 Comment

I have added a benchmark to my answer using cat instead of cell2mat to compare performance.
0

use

 Output = cell2mat(extInt(vec))

Since you want to address the cells in extInt not the content of the cells

extInt(vec)
extInt{vec}

try those to see whats going on

2 Comments

Why'd you give the same answer as nilZ0r four minutes later? And that without any effort to explain why that is happening.
@Adriaan as you said it was just 4 minutes. That is a reasonably short time to expect overlap in answers. Why would you question someone for that?

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.