3
$\begingroup$

Given a table of values, I know how to find find maximum values, but how do I find the position of the maximum value in each column.

For example, given

{ {0.803279, 0.958913, 0.600443, 0.928255, 0.425632, 0.165858}, 
  {0.550107, 0.929972, 0.990928, 0.110509, 0.803279, 0.939139}, 
  {0.693203, 0.823982, 0.645499, 0.617851, 0.461366, 0.252978}, 
  {0.277155, 0.321569, 0.796915, 0.976772, 0.462962, 0.944314} }

what so I apply to get

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

especially in cases where the maximum may not be unique (e.g. two columns could have the same maximum value).

$\endgroup$
1
  • $\begingroup$ Related: 18660 $\endgroup$
    – Michael E2
    Commented Nov 14, 2014 at 19:49

6 Answers 6

5
$\begingroup$

You can use this (where t is your dataset):

Ordering[#, -1] & /@ Transpose[t]

which produces

{{1}, {1}, {2}, {4}, {2}, {2}}

Incidentally, the list of positions you gave in your question is wrong (the 4th element should be {4,4}, and the 6th element should be {2,6}).

The above method omits the first coordinates in your expected output, since they are redundant. If you want to have them anyways, do this:

{Flatten[Ordering[#, -1] & /@ Transpose[t]], Range[6]}\[Transpose]

which gives

{{1, 1}, {1, 2}, {2, 3}, {4, 4}, {2, 5}, {4, 6}}
$\endgroup$
2
  • 2
    $\begingroup$ +1, Nice solution for Ordering[#, -1] & /@ Transpose[t] $\endgroup$
    – xyz
    Commented Nov 15, 2014 at 2:31
  • 1
    $\begingroup$ @DumpsterDoofus this is a neat answer +1, it does not deal with repeated maxima in column, however.:) $\endgroup$
    – ubpdqn
    Commented Nov 15, 2014 at 11:12
3
$\begingroup$

Dealing with repeated maxima and to reproduce the expressed desired output:

func[list_] := 
 Join @@ MapIndexed[Thread[{First /@ Position[#, Max@#], First@#2}] &,
    Transpose[list]]

Testing

test = {{0.803279, 0.958913, 0.600443, 0.928255, 0.425632, 
   0.165858}, {0.550107, 0.929972, 0.990928, 0.110509, 0.803279, 
   0.939139}, {0.693203, 0.823982, 0.645499, 0.617851, 0.461366, 
   0.252978}, {0.277155, 0.321569, 0.796915, 0.976772, 0.462962, 
   0.944314}};
func[test]

yields:

(*{{1, 1}, {1, 2}, {2, 3}, {4, 4}, {2, 5}, {4, 6}}*)

Example with repeated values:

func[{{1, 2, 3}, {3, 4, 3}, {2, 5, 2}, {3, 5, 1}}]

yields:

(*{{2, 1}, {4, 1}, {3, 2}, {4, 2}, {1, 3}, {2, 3}}*)
$\endgroup$
3
$\begingroup$

The solution by @DumpsterDoofus is no doubt the simplest and most elegant Mathematica solution. Just for fun I wrote a more direct construction, that gives both the maxima and their positions.

mat={{0.803279,0.958913,0.600443,0.928255,0.425632,0.165858},
  {0.550107,0.929972,0.990928,0.110509,0.803279,0.939139},
  {0.693203,0.823982,0.645499,0.617851,0.461366,0.252978},
  {0.277155,0.321569,0.796915,0.976772,0.462962,0.944314}};

maxvalues=mat[[1]];
maxpositions=Table[1, {Length[mat[[1]]]}];
Do[
  maxpositions=MapThread[Max, {maxpositions,  n  Sign[mat[[n]] - maxvalues]}];
   maxvalues=MapThread[Max,{maxvalues, mat[[n]]}],
  {n, 2, Length[mat]}];
maxvalues
maxpositions

(* {0.803279,0.958913,0.990928,0.976772,0.803279,0.944314} *)

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

$\endgroup$
1
$\begingroup$

My solution:

data =
 {{0.803279, 0.958913, 0.600443, 0.928255, 0.425632, 0.165858}, 
  {0.550107, 0.929972, 0.990928, 0.110509, 0.803279, 0.939139}, 
  {0.693203, 0.823982, 0.645499, 0.617851, 0.461366, 0.252978},
  {0.277155, 0.321569, 0.796915, 0.976772, 0.462962, 0.944314}}

SortBy[
 Union@
   Flatten[Position[data, #] & /@ (Max /@ Transpose@data), 1], Last]
{{1, 1}, {1, 2}, {2, 3}, {4, 4}, {2, 5}, {4, 6}}
$\endgroup$
1
$\begingroup$
list =
  {{0.803279, 0.958913, 0.600443, 0.928255, 0.425632, 0.165858},
   {0.550107, 0.929972, 0.990928, 0.110509, 0.803279, 0.939139},
   {0.693203, 0.823982, 0.645499, 0.617851, 0.461366, 0.252978},
   {0.277155, 0.321569, 0.796915, 0.976772, 0.462962, 0.944314}};

1.

Using TakeLargest (new in 10.1) and Splice (new in 12.1)

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

To get the desired indexed result:

Flatten /@ MapIndexed[List] @ pos

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

To also get the elements:

Splice @ TakeLargest[# -> {"Element", "Index"}, 1] & /@ Transpose[list]

{{0.803279, 1}, {0.958913, 1}, {0.990928, 2}, {0.976772, 4}, {0.803279, 2}, {0.944314, 4}}

2.

Using PositionLargest (new in 13.2)

Splice @* PositionLargest /@ Transpose[list]

{1, 1, 2, 4, 2, 4}

$\endgroup$
1
$\begingroup$

Using Cases and Position:

list = {{0.803279, 0.958913, 0.600443, 0.928255, 0.425632, 0.165858}, 
        {0.550107, 0.929972, 0.990928, 0.110509, 0.803279, 0.939139}, 
        {0.693203, 0.823982, 0.645499, 0.617851, 0.461366, 0.252978}, 
        {0.277155, 0.321569, 0.796915, 0.976772, 0.462962, 0.944314}};

Position[#, Alternatives @@ Cases[Transpose@#, v_ :> Max[v]] &@#] &@list

(*{{1, 1}, {1, 2}, {2, 3}, {2, 5}, {4, 4}, {4, 6}}*)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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