优雅的方式来掩盖在numpy / pandas中包含nan的事件之间的间隔

时间:2015-10-28 00:20:00

标签: python numpy pandas

假设我有一些包含某些事件的数据,我想测量事件之间的时间。但有时我有nan值,因为没有测量。我不想包括那些间隔,因为我真的不知道那里发生了什么。

例如,给定:

import numpy as np
a = np.array([0, 1, 0, 0, 0, 1, 0, 0, np.nan, np.nan, 1, 0, 0, 0, 0, 1])

我想回到[4, 5],因为第一组之间的间隔是4个索引,第二组之间的间隔是nans,因此被忽略,第三组和第四组之间的间隔是5指数。 [4, nan, 5]也可以作为输出接受。

我可以做以下事情:

a_mod = a.copy()
a_mod[np.isnan(a)] = -1e9  # some value I know is larger than my interval will ever be
a_sum = np.cumsum(a_mod)
a_sum_pts = a_sum[a == 1]
mask = np.diff(a_sum_pts) > 0
events = np.where(a == 1)[0]
intervals = np.diff(events)
good_intervals = intervals[mask]

这确实给了我想要的答案。但这感觉就像一个可怕的黑客。有一个更好的方法吗?也许在熊猫里有什么东西?

2 个答案:

答案 0 :(得分:2)

尝试简单

idx, = np.where(a==1)
nanidx, = np.where(np.isnan(a))

intervals = np.diff(idx)
good_intervals = np.delete(intervals, np.searchsorted(idx, nanidx)-1)

这只是查找1的位置和nan的位置,然后删除包含nan的区间。

-1上的searchsorted说明了np.diff的转变;作为次要警告,如果在第一个nan之前有1 s,则此代码无法正常运行(尽管这很容易解决)。

答案 1 :(得分:0)

您可以使用np.ufunc.reduceat找出哪些片段包含nan,并将其掩盖:

O(n)

这将线性执行,即def sumList(l): if l == []: return 0 else: return l[1:] + [l[0]]