Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I have a list of coordinates like this one:

{{x1,y1},{x2,y2},{x3,y3},...,{xn,yn}}

I need to get the minimum and the maximum of all x-values and the minimum and maximum of all y-values. Is this possible? If I use the in-built Min function for example gives me just the minimum of all x and y values...

share|improve this question

7 Answers 7

up vote 9 down vote accepted

Well, you could extract the y values and then calculate their minimum.

rand = RandomInteger[{0, 9}, {10, 3}]
{{6, 5, 2}, {3, 8, 3}, {0, 4, 0}, {3, 7, 5}, {4, 2, 7}, {6, 4, 5}, {3, 3, 3}, {7, 9, 7}, {4, 5, 5}, {4, 2, 5}}
Min[ rand[[All, 2]] ] (* 1 = x, 2 = y, 3 = z *)
Max[ rand[[All, 2]] ]
2
9

Another approach is of course sorting the list by user-defined rules and then picking the first/last element. For example, the following sorts the list according to ascending y values, and then extracts the min/max from that.

sorted = Sort[rand, #1[[2]] < #2[[2]] &]
sorted[[1, 2]] (* Minimal y *)
sorted[[-1, 2]] (* Maximal y *)
2
9

Note that this actually sorts the whole list, which is far less effective computationally. Normally, min/max functions don't sort, they just search.

share|improve this answer
    
Hi David, thanks a lot for your answer and your help. Harald –  Harald Mar 17 '12 at 21:35
    
Isn't it so that sorting can be O(log(n)) whereas scanning the list for the max or min is at best O(n)? Could it be that soting and picking might be the fastest way? –  Reb.Cabin Mar 18 '12 at 2:28
1  
Comparison based sorting is at least $\mathcal O(n\log n)$. –  David Mar 18 '12 at 4:09

You can use Min[ data[[All, 1]] ] to get the minimum of the x values. Or, to get a bit fancier,

Through /@ {Min, Max} /@ Transpose[data]

will give you the minimum and the maximum of the x and the y values in one go.

share|improve this answer
    
Hi Szabolcs, thanks a lot for your help and your answer to my problem. Harald –  Harald Mar 17 '12 at 21:36
    
@user1276227 Hei Harald and welcome to StackExchange! :-) I hope you'll like it here. I see your account is unregistered. I recommend you register and enter your name in your profile. Also, please do not cross post the same question between multiple SE sites (cross posting to mailing lists or non-SE sites is okay). For Mathematica-related questions this site is best---you'll get answers quickly here. –  Szabolcs Mar 17 '12 at 21:38
8  
Congrats on being the first 10k user! :) –  rm -rf Mar 17 '12 at 22:03

You can also use new functions in version 8 like RankedMax and RankedMin.

list = RandomInteger[{0, 100}, {10, 2}]
{{44, 9}, {74, 0}, {56, 40}, {45, 56}, {0, 76}, {88, 90}, {14, 19},
 {77, 64}, {4, 75}, {81, 56}}

This yields three maximal y- elements :

RankedMax[list[[All, 2]], #] & /@ Range[3]
{90, 76, 75}

while this three minimal x- elements :

RankedMin[list[[All, 1]], #] & /@ Range[3]
{0, 4, 14}

RankedMax[list[[All, 2]], n] gives n-th maximal y-element.

share|improve this answer
    
Hi Artes, thanks a lot for your hints. Never noticed these new functions up to now... Harald –  Harald Mar 17 '12 at 22:47
    
@Harald You can successfully use built-in functions since in general they are optimized. Note e.g. RankedMax[list[[All, 2]], Length@list] is equivalent to Min[[All,2]], though it would be better to use RankedMin[list[[All, 2]], 1]. –  Artes Mar 17 '12 at 23:00
    
@Artes what would you do to your code to get both parts instead of one cordinate? for example to get the nth maximal value of x or y and it outputs the x and y cordinate as well? –  Crisp Aug 28 at 3:40
    
@Crisp Consider using SortBy or new in version 10 MaximalBy, e.g. MaximalBy[ list, Last]. –  Artes Aug 28 at 10:38

Szabolcs's answer is how I would've done it, but just for fun, you can also use an undocumented function Random`Private`MapThreadMin to achieve the same result for the minimum values. However, there isn't an equivalent Random`Private`MapThreadMax, so we just negate the arguments and then the output. The following:

{Random`Private`MapThreadMin[#], -Random`Private`MapThreadMin[-#]} &@ list//Transpose

will give you the same result as Szabolcs's answer. Example:

list = RandomInteger[{0, 9}, {10, 3}];
{Random`Private`MapThreadMin[#], -Random`Private`MapThreadMin[-#]} &@ list//Transpose
Through /@ {Min, Max} /@ Transpose[list]

Out[1]= {{0, 8}, {1, 9}, {2, 9}}
Out[2]= {{0, 8}, {1, 9}, {2, 9}}
share|improve this answer
    
Hi, thanks a lot for your answer, which helps me to learn more and more about Mathematica. Harald –  Harald Mar 17 '12 at 22:45

The more direct application of Map, that is:

{Min@#, Max@#} & /@ Transpose[dat]

is an order of magnitude faster than Szabolcs's pretty but convoluted method:

SetAttributes[timeAvg, HoldFirst]

timeAvg[func_] := 
  Do[If[# > 0.3, Return[#/5^i]] & @@ Timing@Do[func, {5^i}], {i, 0, 15}]

dat = RandomInteger[1*^7, {500000, 2}];

Through /@ {Min, Max} /@ Transpose[dat]; // timeAvg

{Min@#, Max@#} & /@ Transpose[dat]; // timeAvg
0.0362

0.003368
share|improve this answer
    
Hi Mr. Wizard, thanks a lot for your comment and your help, Harald –  Harald Mar 17 '12 at 22:48
2  
+1 (already when you answered) but I don't find my method convoluted. I think it's natural once you get used to Through. Of course now that you pointed out that this version is so much faster, I'd use this one. The strange thing is that Through forces the array to be unpacked. I don't understand why. I don't see why this is necessary ... could even call it a bug or an oversight? –  Szabolcs Mar 19 '12 at 20:18
    
@Szabolcs I have to agree that doesn't make sense. Also, convoluted may not have been the best choice of words. –  Mr.Wizard Mar 19 '12 at 22:04

The following, suprisingly, is almost as fast as Mr.Wizard's approach, and it provides added flexibility to get ranks different from Min and Max or ranges of ranks as well as the ability to specify any ordering function:

  {#[[Ordering[#, 1]]], #[[Ordering[#, -1]]]} & /@ Transpose[dat]

Alternatively, one can re-organize the left part:

  #[[Flatten@{Ordering[#, 1], Ordering[#, -1]}]] & /@ Transpose[dat]

Additional flexibility comes from the ability to use the second and third arguments of Ordering.

To get the second smallest and third largest elements, use as

 {#[[Ordering[#, 2]]], #[[Ordering[#, -3]]]} & /@ Transpose[dat]

To get the bottom 4 and top 5 elements:

 {#[[Ordering[#, {1,4}]]], #[[Ordering[#, {-5,-1}]]]} & /@ Transpose[dat]

To get odd-ranked and even-ranked elements:

 {#[[Ordering[#, {1,-1,2}]]], #[[Ordering[#, {2,-1,2}]]]} & /@ Transpose[dat]

To get the smallest and largest elements when elements are ordered by Abs:

 {#[[Ordering[#, 1, Abs[#1] < Abs[#2] &]]],
  #[[Ordering[#, -1,Abs[#1] < Abs[#2] &]]]} & /@ Transpose[dat]

etc...

share|improve this answer
    
+1. I did think about ordering, but used to think it was going to be terribly slow. –  FJRA Mar 18 '12 at 19:02
    
@FJRA, actually Ordering is usually faster than alternatives like Sort, SortBy; but I too was surprised to find that it is as fast as it is when the task is just plain vanilla Min,Max. –  kguler Mar 19 '12 at 0:10
trr = RandomReal[{1, 7}, {5, 2}]

Select[trr, #[[2]] == Max[trr[[All, 2]]] &](*Maximal y, in the pairs {xi,yi} *)

Select[trr, #[[1]] == Min[trr[[All, 1]]] &](*Minimal x, in the pairs {xi,yi} *)
share|improve this answer
1  
I think your answer is slightly different from what OP asked for. –  Silvia May 15 '13 at 11:49

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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