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.

Let's create some sample data

n = 10;
data = Table[{RandomReal[], RandomReal[], RandomReal[], RandomReal[], 
RandomInteger[{-1, 2}], RandomInteger[{0, 15000}]}, {i, 1, n}]

Now, I want to find the minimum and the maximum value of the last column (#6) only when the fifth one has an integer value 1 or 2, thus excluding the -1 and 0.

Any suggestions?

share|improve this question

4 Answers 4

up vote 0 down vote accepted

Not pretty, but work

#@Select[data,MemberQ[#,Alternatives@@{1,2}]&][[All,6]]&/@{Max,Min}
share|improve this answer
    
It works like a charm. Thank you very much! –  Vaggelis_Z Jul 29 at 9:11
    
@Vaggelis_Z I suggest you use a different method. This code performs the same selection redundantly, once for Max and once for Min. –  Mr.Wizard Jul 30 at 12:56
    
@Mr.Wizard I don't quite understand your point. Could you elaborate (explain) it a little bit more? –  Vaggelis_Z Jul 30 at 14:30
    
@Vaggelis_Z My point is that this is not efficiently written. Select is part of the function that is mapped to {Max,Min} therefor the selection is run twice. Worse, the selection function is not focused on the fifth column: it is checking for a 1 or 2 anywhere in the sublist. While for the given example this does not change the result it is hardly correct. –  Mr.Wizard Jul 30 at 14:50
    
@Vaggelis_Z If it is the use of Alternatives that you like consider: {Min@#, Max@#} & @ Pick[#6, #5, 1 | 2] & @@ (data\[Transpose]) –  Mr.Wizard Jul 30 at 14:55

Though it isn't the focus of your question there is a much faster way to generate your example data:

Join[RandomReal[1, {n, 4}], Transpose[RandomInteger[#, n] & /@ {{-1, 2}, 15000}], 2]

For the problem itself I also chose Pick but I used Transpose and Positive instead:

{Min@#, Max@#} & @ Pick[#6, Positive @ #5] & @@ (data\[Transpose])

This proves to be about twice as fast as sebhofer's code:

n = 1*^6;

data = Join[RandomReal[1, {n, 4}], Transpose[RandomInteger[#, n] & /@ {{-1, 2}, 15000}], 2]

{Min@#, Max@#} & @ Pick[#6, Positive @ #5] & @@ (data\[Transpose])         // Timing // First

Through[{Max, Min}@Pick[data[[;; , 6]], HeavisideTheta@data[[;; , 5]], 1]] // Timing // First
0.162241

0.343202

(Timings performed in version 10.0.)

share|improve this answer
    
The Pick method seems the most intuitive. I was about to post my answer but I see that @Mr.Wizard already came up with it (of course). –  seismatica Jul 30 at 0:43
    
Well that was just a matter of time, wasn't it... :) –  sebhofer Jul 30 at 8:23
    
I think my new version is even faster though! –  sebhofer Jul 30 at 13:11
    
@sebhofer I can confirm that it is faster, and I'm not too surprised. Nevertheless like using Transpose as it lets me address columns with simply #5 or #6 which IMO make things much nicer to read. By the way you already had my vote. :-) –  Mr.Wizard Jul 30 at 14:15
    
@sebhofer It seems the transpose is costly because the data is not packed. Thread is actually faster in this case, but it doesn't match Part. With packed data such as data = RandomReal[{-2, 2}, {1*^6, 6}]; my code is still slightly faster than yours. :^) –  Mr.Wizard Jul 30 at 14:19

Slightly faster alternative (about factor of 10 speedup compared to accepted solution):

Through[{Max, Min}@Pick[data[[;; , 6]], HeavisideTheta@data[[;; , 5]], 1]]

Edit

And even a bit better

Through[{Max, Min}@Pick[data[[;; , 6]], Positive@data[[;; , 5]]]]

which I think is even a bit faster than Mr.Wizard's current method.

share|improve this answer

MaximalBy, build-in function in v10.0.0.

f[list_] := 
  With[{x = list[[5]]}, If[x == 1 || x == 2, list[[6]], -1]];
MaximalBy[data, f]
share|improve this answer
    
Unfortunately, I have v9.0. Thanks BTW. –  Vaggelis_Z Jul 29 at 9:07

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.