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?
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