Search code examples
matlabmatrixcell-array

Order of elements in cell array constructed by accumarray


What I'm trying to do: given a 2D matrix, get the column indices of the elements in each row that satisfy some particular condition.

For example, say my matrix is

M = [16 2 3 13; 5 11 10 8; 9 7 6 12; 4 14 15 1]

and my condition is M>6. Then my desired output would be something like

Indices = {[1 4]'; [2 3 4]'; [1 2 4]'; [2 3]';}

After reading the answers to this similar question I came up with this partial solution using find and accumarray:

[ix, iy] = find(M>6);
Indices = accumarray(ix,iy,[],@(iy){iy});

This gives very nearly the results I want -- in fact, the indices are all right, but they're not ordered the way I expected. For example, Indices{2} = [2 4 3]' instead of [2 3 4]', and I can't understand why. There are 3 occurrences of 2 in ix, at indices 3, 6, and 9. The corresponding values of iy at those indices are 2, 3, and 4, in that order. What exactly is creating the observed order? Is it just arbitrary? Is there a way to force it to be what I want, other than sorting each element of Indices afterwards?


Solution

  • Here's one way to solve it with arrayfun -

    idx = arrayfun(@(x) find(M(x,:)>6),1:size(M,1),'Uni',0)
    

    Display output wtih celldisp(idx) -

    idx{1} =
         1     4
    idx{2} =
         2     3     4
    idx{3} =
         1     2     4
    idx{4} =
         2     3
    

    To continue working with accumarray, you can wrap iy with sort to get your desired output which doesn't look too pretty maybe -

    Indices = accumarray(ix,iy,[],@(iy){sort(iy)})
    

    Output -

    >> celldisp(Indices)
    Indices{1} =
         1
         4
    Indices{2} =
         2
         3
         4
    Indices{3} =
         1
         2
         4
    Indices{4} =
         2
         3