# Position of n largest elements in each row in a matrix that satisfies certain criterion

Suppose I have a matrix m={{1,2,3},{3,-2,1/3}};

I want to find the positions of, for example, 2 largest elements in each row that is above 1/2.

So, in m, 2 and 3 are the ones in the first row and 3 is the one in the second row. Thus, the output should be their positions:

{{1,2},{1,3},{2,1}}

I tried to use Position[m, _?(# > 1/2 &)] but this will only find the position of elements that is above 1/2..

How can I do this?

Update: Shorter variations:

ClearAll[taken, takem, takek]
taken[condition_, n_] := Apply[Join] @*
Select[Function[x, condition @ #[[x]]]] @ TakeLargest[# -> "Index", n]}] &]

takem[condition_, m_] := Apply[Join] @*
Select[Function[x, condition @ #[[x]]]] @ Ordering[#, -m]}] &]

takek[condition_, k_] := MapIndexed[Sequence @@ Thread[{#2[[1]], #}] &] @*
Map[Cases[{a_ /; condition[a], b_} :> b] @
Nearest[# -> {"Element", "Index"}, Max @ #, k] &]


Examples:

taken[GreaterEqualThan[1/2], 2] @ m

{{1, 3}, {1, 2}, {2, 1}}

takem[GreaterEqualThan[1/2], 2] @ m

{{1, 3}, {1, 2}, {2, 1}}

takek[GreaterEqualThan[1/2], 2] @ m

{{1, 3}, {1, 2}, {2, 1}}


ClearAll[take]
take[condition_, n_] := Apply[Join] @*
Map[Map[#Index &] @
Select[condition @ #Element &] @
TakeLargest[# -> All, n]&]


Examples:

take[GreaterEqualThan[1/2], 2] @ m

{{1, 3}, {1, 2}, {2, 1}}

take[GreaterEqualThan[0], 2] @ m

{{1, 3}, {1, 2}, {2, 1}, {2, 3}}

take[GreaterEqualThan[2], 3] @ {Range[5], Range[-3, 2], Reverse @ Range[4, 8]}

{{1, 5}, {1, 4}, {1, 3}, {2, 6}, {3, 1}, {3, 2}, {3, 3}}


TakeLargest is the function you are looking for. And then Select to get the numbers above 1/2:

m = {{1, 2, 3}, {3, -2, 1/3}};
t = TakeLargest[#, 2] & /@ m
sel=Select[# > 1/2 &] /@ t

(*{{3, 2}, {3}}*)


And then finally the positions. We first determine the position inside sel and then prepend the row number:

pos = Flatten /@ MapThread[Function[{x, y}, Position[x, #] & /@ y], {m, sel}]
MapIndexed[Function[{x, y}, {Sequence @@ y, #} & /@ x], pos]

(* {{{1, 3}, {1, 2}}, {{2, 1}}} *)

• OP is looking for positions of these, not the actual values. Commented Feb 16, 2021 at 9:33
• Just give me a minute, I am still writing. Commented Feb 16, 2021 at 9:41

We can also use the new PositionLargest (since 13.2)

m = {{1, 2, 3}, {3, -2, 1/3}};


Get positions:

p = Flatten @ PositionLargest[#, Min[2, Count[#, u_ /; u > 0.5]]] & /@ m


{{3, 2}, {1}}

Index them:

Flatten[#, 1] & @ MapIndexed[Thread[{#2[[1]], #1}] &] @ p


{{1, 3}, {1, 2}, {2, 1}}