简体   繁体   中英

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?

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)

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 .

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

您可以使用简单的列表理解来首先过滤掉无:

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

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.

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

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

Pandas DataFrame have their own function,

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM