慢慢从Matlab过渡到Python ......
我有这份表格的清单
list1 = [[1, 2, nan], [3, 7, 8], [1, 1, 1], [10, -1, nan]]
和另一个具有相同数量项目的列表
list2 = [1, 2, 3, 4]
我正在尝试提取list1中不包含任何nan值的元素,以及list2中的相应元素,即结果应为:
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))]
这显然对list2毫无用处。
或者,以下逻辑索引尝试 不 工作(“索引必须是整数,而不是列表”)
idx = [any(isnan(x)) for x in list1]
list1_clean = list1[idx]
list2_clean = list2[idx]
我确定这是微不足道的,但我无法弄明白,帮助赞赏!
答案 0 :(得分:6)
您可以使用zip
。
zip
从传递给它的迭代中返回相同索引上的项目。
>>> 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)]
现在解压缩out
以获得所需的输出:
>>> 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
,因为它返回一个迭代器。
答案 1 :(得分:2)
你可以这样做:
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)
建议使用izip
模块中的itertools
,它使用迭代器,可以根据您的问题节省大量内存。
而不是~
,您可以使用numpy.logical_not()
,这可能更具可读性。
欢迎使用Python!
答案 2 :(得分:0)
这应该有效。我们使用math.isnan
检查号码是否为NaN。
如果原始列表中的所有元素都不是list1_clean
,我们会在list2_clean
和NaN
中插入一个元素。要检查这一点,我们使用any
函数,如果iterable的任何元素为True
,则返回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(...)
any(iterable) -> bool
Return True if bool(x) is True for any x in the iterable.
isnan
功能 - >
isnan(...)
isnan(x) -> bool
Check if float x is not a number (NaN).