Using the "find" function with cell arrays in MATLAB?

133 visualizzazioni (ultimi 30 giorni)
Hello, I have a cell that contains a lot of data. Let's say this cell, c, has 10 matrices, each being 100x2 (i.e., it is 2-dimensional). So here C= {[100x2], [100x2],...[100x2]}. What I need to do is search each array inside this cell, and find where the value of the first column is less than 401, and also greater than 399 (e.g., find(c(:,1)>399 & c(:,1)<401), although this is probably wrong). I am exclusively focusing this analysis on only the first column of each matrix. Importantly, I need to be able to store the indices where these occur in a new variable. My question: is there a simple way to do this using the "cellfun" function in MATLAB? I'm still getting used to this function and I'm having a hard time telling what I can and can't do with it, or when it's better to just use a for loop. Is there perhaps an even simpler method I'm not aware of? I would really appreciate any help.

Risposte (2)

Star Strider
Star Strider il 25 Feb 2015
I’m not opposed to using cellfun, but it might be easier in your situation to extract them to double arrays with cell2mat, and then do the find operations on them there. Cell arrays are quite useful and I use them frequently, but sometimes it’s easier to extract the data as double arrays. Yours would appear to be one.
  2 Commenti
John Alperto
John Alperto il 25 Feb 2015
Wait, you suggest I extract each individual part of the cell into a different array? Wouldn't I still have to use a cell to keep them all in one variable? Or are you suggesting I do a for loop and store each resulting vector into a different variable? I guess I'm not picturing what you're saying exactly, sorry.
Star Strider
Star Strider il 25 Feb 2015
That you have a compound search condition:
find(c(:,1)>399 & c(:,1)<401)
might make converting them to double and then using find is easiest. You can use a cell array to keep track of the indices find returns. A for loop would make this easier. Loops really aren’t evil!
If you want to use cellfun, these simple bits of archived code might offer an option:
First Example:
MyArray = {3 [] 3 []};
idx = find(cellfun(@isempty, MyArray));
MyArray(idx) = {0};
Second Example:
x = randi(10, 15, 10);
x(:,5) = 99.9*ones(15,1);
Neg = {x};
Idx = cellfun(@(x) find(x == 99.9), Neg, 'Uni',0);
The for loop might still be necessary in order to process all of them efficiently.

Accedi per commentare.


Guillaume
Guillaume il 25 Feb 2015
One possible way: (prerequisite: all the matrices in C are 2d and the same size):
allmatrices = cat(3, C{:});
firstcolumns = squeeze(allmatrices(:, 1, :));
[rowindices, matrixnumber] = find(firstcolumns > 399 & firstcolumns < 401);
%to redistribute the above two values in a cell array if wanted:
rows = accumarray(matrixnumber, rowindices, [numel(C) 1], @(v) {v})
Or using cellfun:
rows = cellfun(@(m) find(m(:, 1) > 399 & m(:, 1) < 401), C, 'UniformOutput', false)
This may or may not be slower than the other method (but does not have any prerequisite)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by