通过groupby计算列表或数组中连续重复的nan

时间:2014-06-02 01:13:24

标签: python

这与我很久以前的问题有关。 我想从列表中算出nan,但它不是字符串,而是真正的nan,例如。

b = [1.0, nan, nan, 3.5 ...]

从这个列表中,我想算出连续纳米的长度。在上面的情况下,数字将是2。

我的代码是:

 v = [len(list(group)) for key, group in groupby(b) if key== np.isnan(key)]

在这种情况下,v的结果为空。

当我将代码更改为:

  v = [len(list(group)) for key, group in groupby(b) if key== np.isnan(b)]

错误发生在ValueError:具有多个元素的数组的真值是不明确的。使用a.any()或a.all()。

请您给我任何想法或帮助吗?

2 个答案:

答案 0 :(得分:3)

v = [len(list(group)) for key, group in groupby(b) if key== np.isnan(key)]

您将key(列表中的元素)与np.isnan(key)进行比较,这是一个布尔值。此外,由于nan != nan,这甚至可能不会将相邻的nans组合在一起。

v = [len(list(group)) for key, group in groupby(b) if key== np.isnan(b)]

现在,您将key(一个列表元素)与整个布尔numpy数组进行比较。这不是你想要做的事情,numpy非常合理地告诉你,它没有规范的方式让它知道你想要bool(key == np.isnan(b))做什么,所以它无法确定是否采用if

也许像

>>> b = np.array([1, np.nan, np.nan, 2, 3, np.nan, 4])
>>> v = [len(list(group)) for key, group in groupby(b, key=np.isnan) if key]
>>> v
[2, 1]

会奏效。各个部分看起来像

>>> vv = [(key, list(group)) for key, group in groupby(b, key=np.isnan)]
>>> vv
[(False, [1.0]), (True, [nan, nan]), (False, [2.0, 3.0]), (True, [nan]), (False, [4.0])]

(更多的想法,你可能会得到一个矢量化的numpy方法,但让我们开始使用你熟悉的工具。)


正如@ user2357112在评论中指出的那样,由于我们只关心纳米簇的长度,我们可以通过一次性isnan检查来优化这一点:

>>> b
array([  1.,  nan,  nan,   2.,   3.,  nan,   4.])
>>> np.isnan(b)
array([False,  True,  True, False, False,  True, False], dtype=bool)
>>> [len(list(g)) for k,g in groupby(np.isnan(b)) if k]
[2, 1]

答案 1 :(得分:0)

您可以执行以下操作:

>>> from numpy import nan
>>> from itertools import groupby
>>> x = [1.0, nan, nan, 3.5, nan, nan, nan]
>>> [item[1] for item in [(c,len(list(cgen))) for c,cgen in groupby(x)] if item[0] is nan]
[2, 3]
>>> 

这使用groupby然后获取所有出现次数。