Python 列表理解与逻辑索引

Python 列表理解与逻辑索引,python,list,matrix-indexing,Python,List,Matrix Indexing,慢慢地从Matlab转换到Python 我有这张表格的清单 list1 = [[1, 2, nan], [3, 7, 8], [1, 1, 1], [10, -1, nan]] 和另一个项目数相同的列表 list2 = [1, 2, 3, 4] 我试图提取列表1中不包含任何nan值的元素,以及列表2中相应的元素,即结果应为: list1_clean = [[3, 7, 8], [1, 1, 1]] list2_clean = [2, 3] 在Matlab中,通过逻辑索引很容易做到这一点

慢慢地从Matlab转换到Python

我有这张表格的清单

list1 = [[1, 2, nan], [3, 7, 8], [1, 1, 1], [10, -1, nan]] 
和另一个项目数相同的列表

list2 = [1, 2, 3, 4]
我试图提取列表1中不包含任何nan值的元素,以及列表2中相应的元素,即结果应为:

list1_clean = [[3, 7, 8], [1, 1, 1]]
list2_clean = [2, 3]
在Matlab中,通过逻辑索引很容易做到这一点

在这里,我感觉对某种形式的列表理解会起到作用,但我被困在:

list1_clean = [x for x in list1 if not any(isnan(x))]
这显然对清单2没有用处

或者,以下逻辑索引尝试不起作用(“索引必须是整数,而不是列表”)


我敢肯定这是一件非常琐碎的事情,但我无法理解,谢谢你的帮助

您可以使用
zip

zip
从传递给它的iterables返回同一索引上的项

>>> from math import isnan
>>> list1 = [[1, 2, 'nan'], [3, 7, 8], [1, 1, 1], [10, -1,'nan']]
>>> list2 = [1, 2, 3, 4]
>>> out = [(x,y)  for x,y in zip(list1,list2) 
                                         if not any(isnan(float(z)) for z in x)]

>>> out
[([3, 7, 8], 2), ([1, 1, 1], 3)]
现在将
解压缩
,以获得所需的输出:

>>> list1_clean, list2_clean = map(list, zip(*out))
>>> list1_clean
[[3, 7, 8], [1, 1, 1]]
>>> list2_clean
[2, 3]
有关
zip的帮助信息

>>> print zip.__doc__
zip(seq1 [, seq2 [...]]) -> [(seq1[0], seq2[0] ...), (...)]

Return a list of tuples, where each tuple contains the i-th element
from each of the argument sequences.  The returned list is truncated
in length to the length of the shortest argument sequence.

如果您想要一个内存高效的解决方案,因为它返回一个迭代器,那么可以使用
itertools.izip

这应该可以。我们检查一个数字是否为NaN或未使用

如果原始列表中没有一个元素是
NaN
,则在
list1\u clean
list2\u clean
中插入一个元素。为了检查这一点,我们使用函数返回
True
,如果iterable的任何元素是
True

>>> list1 = [[1, 2, float('NaN')], [3, 7, 8], [1, 1, 1], [10, -1, float('NaN')]]
>>> list2 = [1, 2, 3, 4]
>>> from math import isnan
>>> list1_clean = [elem for elem in list1 if not any([isnan(element) for element in elem])]
>>> list1_clean
[[3, 7, 8], [1, 1, 1]]
>>> list2_clean = [list2[index] for index, elem in enumerate(list1) if not any([isnan(element) for element in elem])]
>>> list2_clean
[2, 3]
要使其更小并避免使用
zip
,您可以这样做

>>> cleanList = [(elem, list2[index]) for index, elem in enumerate(list1) if not any([isnan(element) for element in elem])]
>>> cleanList
[([3, 7, 8], 2), ([1, 1, 1], 3)]
>>> list1_clean = [elem[0] for elem in cleanList]
>>> list2_clean = [elem[1] for elem in cleanList]
任意
功能->

any(...)
    any(iterable) -> bool

    Return True if bool(x) is True for any x in the iterable.
isnan(...)
    isnan(x) -> bool

    Check if float x is not a number (NaN).
isnan
功能->

any(...)
    any(iterable) -> bool

    Return True if bool(x) is True for any x in the iterable.
isnan(...)
    isnan(x) -> bool

    Check if float x is not a number (NaN).

您可以简单地执行以下操作:

ans = [(x,y) for x,y in zip(list1,list2) if all(~isnan(x))]

#[(array([ 3.,  7.,  8.]), 2), (array([ 1.,  1.,  1.]), 3)]
您可以通过以下操作从中提取每个值:

l1, l2 = zip(*ans) 

#l1 = (array([ 3.,  7.,  8.]), array([ 1.,  1.,  1.]))
#l2 = (2,3)
建议使用
itertools
模块中的
izip
,它使用迭代器,根据您的问题,迭代器可以节省大量内存

您可以使用
numpy.logical\u not()
,而不是
~
,这可能更具可读性


欢迎来到Python

要解决您的(“索引必须是整数,而不是列表”)错误,请在数据中对x,y使用
。您在列表中有一个列表,因此您必须说明所有列表。您可能希望使用它,因为它的数组更接近您从Matlab获得的结果(如果您在使用la Matlab进行大量的数字运算,它的性能也更高)。谢谢!但有一个问题是,为什么要用any(isnan(float(z))代替any(isnan(x))——下面的另一张海报使用了一个类似的结构,这对我来说似乎是多余的(而且可读性较差)。这两种方法都有效,但对于较长的一种方法,有什么好的理由吗?@IMK您也可以使用
not any(map(isnan,x))
因为您在某个变量中定义了
nan
,因为我使用了字符串
'nan'
,所以映射到
float
是必需的,否则
isnan
会产生错误。谢谢,我投票选择了前面的答案,这是同样的解决方案。注意到了。伊齐普。很高兴我换成了Python,但还有一些工作要做。