5
$\begingroup$

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?

$\endgroup$
6
$\begingroup$

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}} 
$\endgroup$
5
$\begingroup$

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}}} *)
$\endgroup$
2
  • $\begingroup$ OP is looking for positions of these, not the actual values. $\endgroup$
    – Nasser
    Feb 16 at 9:33
  • $\begingroup$ Just give me a minute, I am still writing. $\endgroup$ Feb 16 at 9:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.