Position of n largest elements in each row in a matrix that satisfies certain criterion
Update: Shorter variations:
ClearAll[taken, takem, takek]
taken[condition_, n_] := Apply[Join] @*
MapIndexed[Thread[{#2[[1]],
Select[Function[x, condition @ #[[x]]]] @ TakeLargest[# -> "Index", n]}] &]
takem[condition_, m_] := Apply[Join] @*
MapIndexed[Thread[{#2[[1]],
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}}
Original answer:
ClearAll[take]
take[condition_, n_] := Apply[Join] @*
MapIndexed[Thread[{#2[[1]], #}] &] @*
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}}} *)