Reputation: 1801
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
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
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
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
Reputation: 402413
First, convert to a numpy array. Specify dtype=np.floatX
, and all those None
s 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
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 None
s 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
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
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
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