1
$\begingroup$

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?

$\endgroup$
0

4 Answers 4

0
$\begingroup$

Not pretty, but work

#@Select[data,MemberQ[#,Alternatives@@{1,2}]&][[All,6]]&/@{Max,Min}
$\endgroup$
5
  • $\begingroup$ It works like a charm. Thank you very much! $\endgroup$
    – Vaggelis_Z
    Commented Jul 29, 2014 at 9:11
  • $\begingroup$ @Vaggelis_Z I suggest you use a different method. This code performs the same selection redundantly, once for Max and once for Min. $\endgroup$
    – Mr.Wizard
    Commented Jul 30, 2014 at 12:56
  • $\begingroup$ @Mr.Wizard I don't quite understand your point. Could you elaborate (explain) it a little bit more? $\endgroup$
    – Vaggelis_Z
    Commented Jul 30, 2014 at 14:30
  • $\begingroup$ @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. $\endgroup$
    – Mr.Wizard
    Commented Jul 30, 2014 at 14:50
  • $\begingroup$ @Vaggelis_Z If it is the use of Alternatives that you like consider: {Min@#, Max@#} & @ Pick[#6, #5, 1 | 2] & @@ (data\[Transpose]) $\endgroup$
    – Mr.Wizard
    Commented Jul 30, 2014 at 14:55
3
$\begingroup$

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.)

$\endgroup$
6
  • $\begingroup$ 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). $\endgroup$
    – seismatica
    Commented Jul 30, 2014 at 0:43
  • $\begingroup$ Well that was just a matter of time, wasn't it... :) $\endgroup$
    – sebhofer
    Commented Jul 30, 2014 at 8:23
  • $\begingroup$ I think my new version is even faster though! $\endgroup$
    – sebhofer
    Commented Jul 30, 2014 at 13:11
  • $\begingroup$ @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. :-) $\endgroup$
    – Mr.Wizard
    Commented Jul 30, 2014 at 14:15
  • $\begingroup$ @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. :^) $\endgroup$
    – Mr.Wizard
    Commented Jul 30, 2014 at 14:19
3
$\begingroup$

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.

$\endgroup$
2
$\begingroup$

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]
$\endgroup$
1
  • $\begingroup$ Unfortunately, I have v9.0. Thanks BTW. $\endgroup$
    – Vaggelis_Z
    Commented Jul 29, 2014 at 9:07

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.