10
$\begingroup$

I have the following set:

list = {{32/39, 1/5, 0, 0, 0}, {5/33, 3/5, 1/3, 0, 3/4}};

I need to find the position of maximum value from each subset. I tried

Position[list, Max[list]]

and it gives the position {{1,1}}. But my result should be {{1,1}, {2,5}}/

$\endgroup$
  • 4
    $\begingroup$ From the documentation for Ordering (=> Props and Relations), to find the position of the maximum element: Ordering[#1, -1] & /@ list -> {{1}, {5}}. See also here $\endgroup$ – user1066 Jan 27 '18 at 13:42
9
$\begingroup$

Here is an answer that makes extensive use of internal functions, but is significantly faster.

maxPositions[list_?MatrixQ] := With[
    {
    mask = UnitStep @ Subtract[
        list,
        Random`Private`MapThreadMax[Transpose@list]
    ]
    },
    Mod[Random`Private`PositionsOf[Flatten @ mask, 1], Dimensions[list][[2]], 1]
]

The function does not return the indices, only the maxima. Comparison:

data = RandomReal[10, {10^5, 5}];

r1 = maxPositions[data]; //RepeatedTiming
r2 = Position[Unitize[#-Max@#]&/@data,0]; //RepeatedTiming (* kglr *)

Thread[{Range[10^5], r1}] === r2

{0.00737, Null}

{0.088, Null}

True

The other answers are much slower.

Update

It seems that Random`Private`MapThreadMax was introduced between 10.3.1 and 11.1. For versions of Mathematica that don't have that function you can use:

maxPositions[list_?MatrixQ] := With[
    {mask = UnitStep[list + Random`Private`MapThreadMin[-Transpose@list]},
    Mod[Random`Private`PositionsOf[Flatten @ mask, 1], Dimensions[list][[2]], 1]
]
$\endgroup$
  • $\begingroup$ thanks for introducing me to these internal functions. +1 of course :) $\endgroup$ – ubpdqn Jan 27 '18 at 2:39
  • 2
    $\begingroup$ @Carl Woll I tried to use your answer but those Private functions do not get identified, Using windows10, math v11.0 $\endgroup$ – Anxon Pués Jan 27 '18 at 11:48
  • $\begingroup$ Thank you for the help!! $\endgroup$ – Nirmal Baral Jan 30 '18 at 14:43
  • $\begingroup$ Wow, RandomPrivatePositionsOf will be super-helpful. Thanks for introducing me to it! $\endgroup$ – Henrik Schumacher Nov 18 '18 at 17:00
  • $\begingroup$ I'm surprised to see Random`Private`PositionsOf[Range[1., 3.], 2.] comes back unevaluated. $\endgroup$ – Chip Hurst Apr 23 at 13:04
8
$\begingroup$
MapIndexed[
 Join[#2, Position[#, Max[#]][[1]]] &
, list
]
$\endgroup$
  • $\begingroup$ Appreciate it!! $\endgroup$ – Nirmal Baral Jan 30 '18 at 14:43
8
$\begingroup$
Position[Unitize[# - Max @ #]& /@ list, 0]

{{1, 1}, {2, 5}}

Also:

MapIndexed[Join[#2, Ordering[#, -1]]&, list]
Join @@@ MapIndexed[Prepend, Position[#, Max @ #] & /@ list]

{{1, 1}, {2, 5}}

$\endgroup$
  • $\begingroup$ Thanks, it worked!! $\endgroup$ – Nirmal Baral Jan 30 '18 at 14:42
4
$\begingroup$
MapThread[Flatten@{#1, Position[#2, #3]} &,
 {Range@Length@list, list, Max /@ list}]
$\endgroup$
4
$\begingroup$
fun = Compile[{{x, _Real, 1}}, Position[x, Max[x]][[1, 1]] , 
Parallelization -> True, RuntimeAttributes -> {Listable}, RuntimeOptions -> "Speed",  CompilationTarget -> "C"]; 

{Range@Length@Flatten[list, {1}], fun[list]} // Transpose

Compile seems very fast :slightly slower than Carl's r1 on matrix with fewer than 10^4 points, faster on matrix with over 10^5 points)

$\endgroup$
  • $\begingroup$ Thank you so much $\endgroup$ – Nirmal Baral Jan 30 '18 at 14:44
3
$\begingroup$
list = {{32/39, 1/5, 0, 0, 0}, {5/33, 3/5, 1/3, 0, 3/4}};

From the documentation for Max: "Max[{Subscript[x, 1], Subscript[x, 2],…}, {Subscript[y, 1],…},…] yields the largest element of any of the lists." Consequently,

Max[list]

(* 32/39 *)

From the documentation for Position: "Position returns a list of positions in a form suitable for use in Extract, ReplacePart, and MapAt. The form is different from the one used in Part."

pos = Position[list, Max[list]]

(* {{1, 1}} *)

Extract[list, pos]

(* {32/39} *)

If you want the Max of each of the sublists of list

Max /@ list

(* {32/39, 3/4} *)

pos2 = Position[#, Max[#]] & /@ list

(* {{{1}}, {{5}}} *)

Extract[list[[#]], pos2[[#]]] & /@ {1, 2}

(* {{32/39}, {3/4}} *)
$\endgroup$
  • $\begingroup$ thank you for it $\endgroup$ – Nirmal Baral Jan 30 '18 at 14:44
3
$\begingroup$

This also works but slow for large list.

Join @@ (Position[list, #] & /@ Max /@ list)

Edit: Above code only works if elements are not repeated.

This one works for all cases and pretty fast.

Transpose@{Range@Length@list, Flatten[Position[#, Max[#]] & /@ list]}
$\endgroup$
  • $\begingroup$ Try list = {{6, 5}, {5, 1}} $\endgroup$ – Kuba Jan 27 '18 at 21:13
  • $\begingroup$ Thank you so much for the help $\endgroup$ – Nirmal Baral Jan 30 '18 at 14:45
0
$\begingroup$

Reinventing the bicycle here, but could be useful to someone.

list = {{32/39, 1/5, 0, 0, 0}, {5/33, 3/5, 1/3, 0, 3/4}};

Table[Flatten[{i, Position[aux = list[[i]], Max[aux]]}], {i, 1, 
Length[list]}]

{{1, 1}, {2, 5}}

$\endgroup$

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.