20
$\begingroup$

Suppose I have a Table:

tab = {1., 2., 3., Indeterminate}

When I type Max[tab] I get Indeterminate, I would like instead to get Max of all points except the Indeterminate (i.e. Max_new_version[tab] = 3).

NB: As a secondary case the answer should also provide a method to do a conditional replacement such that tab will end up looking like (i.e. Indeterminate is replaced by zero).

tab = {1., 2., 3., 0.0}
$\endgroup$

8 Answers 8

17
$\begingroup$

The first approach would be:

Max@Cases[tab, Except[Indeterminate]]
3.

If I understand your second need, that would be:

tab /. Indeterminate -> 0.0
{1., 2., 3., 0.}

Edit

Oleksandr's approach is indeed very fast, for very long lists seems to be over 3-4 times faster then others. Since my first approach was quite straightforward, it is resonable to add another one obvious method which will be very handy (possibly the fastest) when we work with non-numeric lists :

Max@DeleteCases[l, Indeterminate]

This approach is only a bit slower for numeric lists than that by Oleksandr and probably the best for non-numeric data (when Indeterminates are exceptional cases rather than common). To test prerformance issues we take a slightly more natural data, namely lists of real numbers with appended Indeterminate's :

l = RandomChoice[RandomReal[100, 20000]~Append~Indeterminate, {10^7}]; 

and use AbsoluteTimings to compare methods, starting with the most efficient :

maxNoIndeterminate[l] // AbsoluteTiming                   (*Oleksandr*)
{0.7070000, 99.9945}
 Max@DeleteCases[l, Indeterminate] // AbsoluteTiming       (*Artes II *)
{1.1150000, 99.9945}
  Max@Cases[l, Except[Indeterminate]] // AbsoluteTiming     (*Artes I *)
 {2.7720000, 99.9945}
  Max[l /. Indeterminate -> -Infinity] // AbsoluteTiming   (*cormullion*)
 {2.8870000, 99.9945}
  Max@Select[l, NumberQ] // AbsoluteTiming                (*David Skulsky*)
 {3.5120000, 99.9945}
$\endgroup$
3
  • $\begingroup$ For the first approach, how can you deal with multiple cases e.g. Max@Cases[tab, Except[Indeterminate] and Except[Infinity]] $\endgroup$
    – akk
    Feb 27, 2012 at 12:11
  • $\begingroup$ the answer is a = Max@Cases[tab, Except[Infinity | Indeterminate]] $\endgroup$
    – akk
    Feb 27, 2012 at 12:13
  • 3
    $\begingroup$ @akk You could use also Cases[tab, _?NumberQ] $\endgroup$
    – Artes
    Feb 27, 2012 at 12:51
22
$\begingroup$

A faster way than those already given avoids iterating over the list to remove unwanted values, instead replacing Indeterminate wherever it appears by redefining it as -Infinity using Block:

maxNoIndeterminate[lst_] := Block[{Indeterminate = -Infinity}, Max[lst]];

Note that any list containing Indeterminate cannot be a packed array, so there is no reason (at least, not in this case) to replace Indeterminate with a machine number rather than -Infinity. The latter, of course, is correct for all possible inputs, whereas using any finite value is not. (Also, Max[] gives -Infinity, so there is a consistency argument to be made as well.)

Here is a timing comparison:

l = RandomChoice[Range[100] ~Append~ Indeterminate, {10^7}];

Timing[Max@Select[l, NumberQ]] (* 2.140 seconds *)

Timing[Max[l /. Indeterminate -> -Infinity]] (* 1.797 seconds *)

Timing[Max@Cases[l, Except[Indeterminate]]] (* 1.750 seconds *)

Timing@maxNoIndeterminate[l] (* 0.515 seconds *)

Edit

As the above seems a bit too trivial to stand as an answer by itself, we might as well generalize this to Min also:

withoutIndeterminate /: (f : Min | Max)[withoutIndeterminate[args___]] :=
  Block[{Indeterminate = f[]}, f[args]];

l = {1, 2, 3, Indeterminate};

Min@withoutIndeterminate[l] (* -> 1 *)
Max@withoutIndeterminate[l] (* -> 3 *)
$\endgroup$
5
  • $\begingroup$ Oh drat, I was about to post this method. :-) $\endgroup$
    – Mr.Wizard
    Feb 27, 2012 at 15:59
  • $\begingroup$ Although this method is faster for the special case of Max/Min: to get the accepted answer you may or may not wish to add faster methods of the additional information present within the current accepted answer (which I feel answers the sub-question better e.g. (1) how to incorporate Max/Min ignoring +/- infinity values. (2) how to replace portions of the table. (3) how to get the maximum of numeric values only) $\endgroup$
    – akk
    Feb 28, 2012 at 0:51
  • 3
    $\begingroup$ @akk I don't like to treat this site as a point-scoring competition and in any case I think these extensions are obvious. If you find them non-obvious and would like an example of how to do it, I will add that to my answer, but I will not do it simply to one-up someone else. $\endgroup$ Feb 28, 2012 at 1:40
  • $\begingroup$ Ok, in that case I will edit the accepted answer (the one I presume most people will look at) to look at your implementation also. $\endgroup$
    – akk
    Feb 28, 2012 at 8:19
  • $\begingroup$ I just looked at the Intermediate = f[] construct. Clever. It appears that I already upvoted this at some point, otherwise I'd upvote you now. $\endgroup$
    – rcollyer
    Mar 25, 2012 at 1:42
8
$\begingroup$

One more way:

tab = {1., 2., 3., Indeterminate};
Max @ Select[tab, NumberQ]
3.
$\endgroup$
5
$\begingroup$

There is one case else to be added (how rich is Mathematica!):

Max[Replace[l, Indeterminate -> -Infinity, {1}]] // AbsoluteTiming
{0.639738, 99.9987}

which is comparable (in my machine) to:

Max@DeleteCases[l, Indeterminate] // AbsoluteTiming
{0.627598, 99.9987}

And much better than the simple /. :

Max[l /. Indeterminate -> -Infinity] // AbsoluteTiming
{1.309642, 99.9987}
$\endgroup$
5
$\begingroup$

But now suppose that you want to compute both Max and Min of a list containing Indeterminate (in other words, you want {Min[#],Max[#]}&@list)?

Sending Indeterminate to -Infinity is no longer such a great idea as you will get -Infinity for Min. And, of course, if you use Infinity, Max will not come out right.

Actually, you can use the same trick by replacing -Infinity with Sequence[]. Note that both Max[100,Sequence[]] and Min[100,Sequence[]] return 100.

$\endgroup$
1
  • $\begingroup$ Or you can set it to Min[] or Max[] as appropriate (as I did in my answer). Sequence[] also works of course; it might be more appropriate for functions without any extremal value such as Mean and so on. $\endgroup$ Mar 24, 2012 at 21:30
2
$\begingroup$
list = {1., 2., 3., Indeterminate};

Using TakeLargest (new in 10.1)

TakeLargest[list, 1]

{3.}

list = {1, Indeterminate, 3, 5, None, Missing[]};

Getting the 2 largest values

TakeLargest[list, 2]

{5, 3}

Getting the 2 largest values and their indices

TakeLargest[list -> {"Element", "Index"}, 2]

{{5, 4}, {3, 3}}

$\endgroup$
1
$\begingroup$
list = {1., 2., 3., Indeterminate};

Another way using GroupBy:

GroupBy[list, NumericQ, Max][True]

3.

$\endgroup$
0
$\begingroup$

You could write this:

Max1[l_] := Max[l  /. Indeterminate -> 0.0]

so that

Max1[tab]

gives

3.
$\endgroup$
1
  • 2
    $\begingroup$ If you are going to define a function to replace Indeterminate, you really ought to have the rule replace it with -Infinity instead of 0.0. After all, what happens if I pass {-1,-2,Indeterminate}? $\endgroup$
    – nixeagle
    Mar 25, 2012 at 5:39

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.