Chris T.
Chris T.

Reputation: 1801

Getting max value from a list with None elements

I'm trying to get maximal value from a list object that contains nonetype using the following code:

import numpy as np

LIST = [1,2,3,4,5,None]
np.nanmax(LIST)

But I received this error message

'>=' not supported between instances of 'int' and 'NoneType'

Clearly np.nanmax() doesn't work with None. What's the alternative way to get max value from list objects that contain None values?

Upvotes: 11

Views: 22111

Answers (8)

nagendra547
nagendra547

Reputation: 6302

In Python 2

max([i for i in LIST if i is not None])

Simple in Python 3 onwards

max(filter(None.__ne__, LIST))

Or more verbosely

max(filter(lambda v: v is not None, LIST))

Upvotes: 8

shubham mishra
shubham mishra

Reputation: 1234

Pandas DataFrame have their own function,

list.idxmax() return the index of max value by ignoring NaN value. Look this URl for more info.

Upvotes: 0

Wasi
Wasi

Reputation: 1492

use filter to get rid of all the None of the LIST
We are taking advantage of the fact that, filter method takes two parameters. The first one is a function and the second one is an Iterable.
This function must return an element of the Iterable(provided as the second argument) which gets removed from the Iterable. We are passing None as the first argument thus all of the objects that are false (in this case None) of the Iterable (LIST) gets filtered out.

import numpy as np
LIST = [1,2,3,4,5,None]

filtered_list = list(filter(None, LIST))
np.nanmax(filtered_list) 

Edit: This won't remove 0 from the LIST

filtered_list = list(filter(None.__ne__, LIST))

Upvotes: 1

cs95
cs95

Reputation: 402413

First, convert to a numpy array. Specify dtype=np.floatX, and all those Nones will be casted to np.nan type.

import numpy as np

lst = [1, 2, 3, 4, 5, None]

x = np.array(lst, dtype=np.float64)
print(x)
array([  1.,   2.,   3.,   4.,   5.,  nan])

Now, call np.nanmax:

print(np.nanmax(x))
5.0

To return the max as an integer, you can use .astype:

print(np.nanmax(x).astype(int)) # or int(np.nanmax(x))
5

This approach works as of v1.13.1.

Upvotes: 9

Divakar
Divakar

Reputation: 221534

One approach could be -

max([i for i in LIST if i is not None])

Sample runs -

In [184]: LIST = [1,2,3,4,5,None]

In [185]: max([i for i in LIST if i is not None])
Out[185]: 5

In [186]: LIST = [1,2,3,4,5,None, 6, 9]

In [187]: max([i for i in LIST if i is not None])
Out[187]: 9

Based on comments from OP, it seems we could have an input list of all Nones and for that special case, it output should be [None, None, None]. For the otherwise case, the output would be the scalar max value. So, to solve for such a scenario, we could do -

a = [i for i in LIST if i is not None]
out = [None]*3 if len(a)==0 else max(a)

Upvotes: 11

dawg
dawg

Reputation: 103814

If you want to be more specific to take the max of numbers only you can use filter and the numbers abstract base class:

>>> import numbers
>>> filter(lambda e: isinstance(e, numbers.Number), [1,'1',2,None])
[1, 2]

Or, a generator version of this:

>>> max(e for e in [1,'1',2,None] if isinstance(e, numbers.Number))
2

Since this is Python 3, your error is the stricter comparison rules under Python 3:

Python 3.6.1 (default, Mar 23 2017, 16:49:06) 
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 1<None
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'int' and 'NoneType'

Where Python 2 does allow unlike object comparisons:

Python 2.7.13 (default, Jan 15 2017, 08:44:24) 
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 1<None
False
>>> 1>None
True

So when you create a numpy array you are getting an array of Python objects:

>>> np.array([1,2,3,4,5,None])
array([1, 2, 3, 4, 5, None], dtype=object)

So numpy is using the underlying Python 3 comparison rules to compare an array of Python objects which is your error:

>>> np.max(np.array([1,2,3,4,5,None]))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.6/site-packages/numpy/core/fromnumeric.py", line 2252, in amax
    out=out, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/numpy/core/_methods.py", line 26, in _amax
    return umr_maximum(a, axis, None, out, keepdims)
TypeError: '>=' not supported between instances of 'int' and 'NoneType'

So you either need to filter out the None when you create the numpy array:

>>> np.max(np.array([e for e in [1,2,3,4,5,None] if e is not None]))
5

Or convert it to a numpy type that supports nan (and np.int does not have nan):

>>> np.array([1,2,3,4,5,None], dtype=np.float)
array([  1.,   2.,   3.,   4.,   5.,  nan])

But in this case, nan is the max value:

>>> np.max(np.array([1,2,3,4,5,None], dtype=np.float))
nan

So use np.nanmax:

>>> np.nanmax(np.array([1,2,3,4,5,None], dtype=np.float))
5.0

Upvotes: 1

NPE
NPE

Reputation: 500317

Here is what I would do:

>>> max(el for el in LIST if el is not None)
5

It is superficially similar to the other answers, but is subtly different in that it uses a generator expression rather than a list comprehension. The difference is that it doesn't create an intermediate list to store the result of the filtering.

Upvotes: 4

Simon
Simon

Reputation: 333

You can use a simple list-comprehension to first filter out Nones:

np.nanmax([x for x in LIST if x is not None])

Upvotes: 1

Related Questions