# Function for finding the nth unique minimum value in a list?

I have this matrix...

mat = Table[{k, 0}, {k, 0, limit}];


After a series of dynamic iterative operations, some of the 0 initialized entries (i.e., those of the 2nd column of mat, i.e., mat[[All, 2]]) are replaced w/ positive integers, e.g.,

mat = {{0,78},{1,0},{2,0},{3,11},{4,11},{5,11},...,{limit,0}}


I realize that there are several standard ways for retrieving the nth minimum value of mat[[All, 2]] but, since mat has so many 0s, they do not help me.

I am looking for a standard/elegant/efficient way to find the nth UNIQUE min value of mat, along w/ its associated row index, e.g., if limit = 6 & I wanted to find the 2nd min-value/index pair, executing...

Print[UniqueMin[mat[[All, 2]], 2]];


would output...

{4,11}


Bc 11 was the 2nd smallest unique value in mat & row 4 was where it 1st occurred.

• Why {4,11}, not {3,11}? Apr 15, 2019 at 6:25
• @corey979 Bc Mathematica starts index @ 1, not 0. You'd be right, if I was asking for the associated row value, but I asked for the associated row index. Apr 15, 2019 at 6:39

## 4 Answers

UniqueMin[list_?VectorQ, n_Integer?Positive] :=
Module[{min = Union[list][[n]]},
{Position[list, min][[1, 1]], min}]

mat = {{0, 78}, {1, 0}, {2, 0}, {3, 11}, {4, 11}, {5, 11}};

UniqueMin[mat[[All, 2]], 2]

(* {4, 11} *)

mat = {{0, 78}, {1, 0}, {2, 0}, {3, 11}, {4, 11}, {5, 11}};


Using Sort and FirstPosition:

{FirstPosition[mat, {_, #}][[1]], #} &@Sort[Union[mat[[All, 2]]]][[2]]

(*{4, 11}*)

mat = {{0, 78}, {1, 0}, {2, 0}, {3, 11}, {4, 11}, {5, 11}};


Using TakeSmallestBy

Last @ TakeSmallestBy[Union[mat] -> {"Index", "Element"}, First, 2]


{2, {1, 0}}

Revision

As Daniel Lichtblau commented the above answer is wrong. A correct answer, using his suggested PositionSmallest, would be:

{#, mat[[#, -1]]} & @ PositionSmallest[mat[[All, 2]], 2][[-1, 1]]


{4, 11}

• The position to be found her eis actually 4 though. In[1135]:= mat = {{0, 78}, {1, 0}, {2, 0}, {3, 11}, {4, 11}, {5, 11}, {33, 0}}; posn = First[Last[PositionSmallest[mat[[All, 2]], 2]]] Out[1136]= 4 Feb 2 at 0:53
• Thank you, Daniel, see revision
– eldo
Feb 2 at 7:31

An alternative approach would use PositionIndex followed by KeySort

The variants below differ in either accessing the parts of the result or using a pattern match (which is slightly slower)

(* version 1*)
Clear[UniqueMin]

UniqueMin[list_?VectorQ, n_Integer?Positive] := With[
{entry = Take[#, {n}]& @ KeySort @ PositionIndex @ list},
{entry[[1, 1]], Keys[entry][[1]]}]

UniqueMin[mat[[All, 2]], 2]
(* {4, 11} *)

(* version 2 *)
Clear[UniqueMin]

UniqueMin[list_?VectorQ, n_Integer?Positive] :=
With[{entry = Take[#, {n}]& @ KeySort @ PositionIndex @ list},
Replace[entry, Association[Rule[x_, List[y_, ___]]] :> {y, x}]]

UniqueMin[mat[[All, 2]], 2]
(* {4, 11} *)

$$$$
`