# Finding position of the maximum value of each subset

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}}/

• 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 Jan 27, 2018 at 13:42

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

maxPositions[list_?MatrixQ] := With[
{
list,
RandomPrivateMapThreadMax[Transpose@list]
]
},
Mod[RandomPrivatePositionsOf[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 *)



{0.00737, Null}

{0.088, Null}

True

The other answers are much slower.

Update

It seems that RandomPrivateMapThreadMax 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 + RandomPrivateMapThreadMin[-Transpose@list]},
Mod[RandomPrivatePositionsOf[Flatten @ mask, 1], Dimensions[list][[2]], 1]
]

• thanks for introducing me to these internal functions. +1 of course :) Jan 27, 2018 at 2:39
• @Carl Woll I tried to use your answer but those Private functions do not get identified, Using windows10, math v11.0 Jan 27, 2018 at 11:48
• Thank you for the help!! Jan 30, 2018 at 14:43
• Wow, RandomPrivatePositionsOf will be super-helpful. Thanks for introducing me to it! Nov 18, 2018 at 17:00
• I'm surprised to see RandomPrivatePositionsOf[Range[1., 3.], 2.] comes back unevaluated. Apr 23, 2019 at 13:04
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}}

• Thanks, it worked!! Jan 30, 2018 at 14:42
MapIndexed[
Join[#2, Position[#, Max[#]][[1]]] &
, list
]

• Appreciate it!! Jan 30, 2018 at 14:43
• @Kuba Is this solution robust for a list of floats? Mar 29, 2020 at 21:48
• @AlGuy I am not sure but I would say probably because the number matched by position was earlier picked by Max from that sublist, it exactly that number should be found.
– Kuba
Mar 30, 2020 at 6:16
MapThread[Flatten@{#1, Position[#2, #3]} &,
{Range@Length@list, list, Max /@ list}]

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}} *)

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)

• Thank you so much Jan 30, 2018 at 14:44

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]}

• Try list = {{6, 5}, {5, 1}}
– Kuba
Jan 27, 2018 at 21:13
• Thank you so much for the help Jan 30, 2018 at 14:45

Since Version 13.2 there is PositionLargest:

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

ps = PositionLargest /@ list


{{1}, {5}}

mi = MapIndexed[{#2[[1]], #1[[1]]} &] @ ps


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

Extract[mi] @ list


• Thanks for pointing to PositionLargest (+1). I simply cannot remember this one. However, for X = RandomReal[{-1, 1}, {10000000}];, a call to Ordering[X, -1] takes just 0.0455106 seconds on my machine while PositionLargest[X] requires 0.385012 seconds. More than 8 times as long! (And more than 60 times as long as a similar C++ function would take...) =/ Jan 7 at 14:08
• Thanks, Henrik, I wasn't aware that PositionLargest  is such a poor performer. Many of the newer functions (all of the Sequence-functions, DeleteElements etc.) are pretty slow. I hope, that WR will accelerate them in future releases.
– eldo
Jan 7 at 17:05

Another method using MaximalBy:

Position[list, #][[1]] & @@@ (list // Map[x |-> MaximalBy[x, Position]])

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


Or using SortBy:

Position[list, #][[1]] & /@ Last /@ (SortBy[#, Position] & /@ list)

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


Or using GroupBy:

Values@((x |-> Position[list, x][[1]]) /@ AssociationMap[Reverse, GroupBy[list, x |-> Max[x]]])

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


Another possibility is to use GroupBy, Position and KeyMap as follows:

Keys@KeyMap[Position[list, #][[1]] &, GroupBy[list, Max]]

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


We could also use TakeLargest

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

max = Splice @ TakeLargest[# -> All, 1] & /@ list


Dataset @ max


Values @ max


{{32/39, 1}, {3/4, 5}}

To only get the positions:

Lookup[max, "Index"]


{1, 5}

Splice @ TakeLargest[# -> "Index", 1] & /@ list


{1, 5}

Positions of the two largest elements:

TakeLargest[# -> "Index", 2] & /@ list


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

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

Using Threshold:

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

pos = list // Map[Threshold[#, {"LargestValues", 1}] &] //
Position[#, Except[0], {2}, Heads -> False] & //
GatherBy[#, First] &


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

Extract[list, #] & /@ pos


{{32/39}, {3/4}}