获取布尔数组中至少n个连续False值的第一个块的索引

时间:2018-04-06 13:20:25

标签: python numpy boolean cumsum

我有一个numpy布尔数组

w=np.array([True,False,True,True,False,False,False])

我想获得第一次有n_at_least个假值的索引。 比如这里

`n_at_least`=1 -> desired_index=1

`n_at_least`=3 -> desired_index=4

我试过了

np.cumsum(~w)

每次遇到False值时都会增加。 但是,当遇到True时,计数器不会再次从0开始,所以我只获得False个元素的总数,而不是最后连续的计数。

6 个答案:

答案 0 :(得分:4)

这是一个O(n)numpy解决方案:

yarn add -D coffee-script

答案 1 :(得分:3)

我认为你陷入了只想要使用numpy功能的numpy陷阱。 python有什么问题?此解决方案为O(n)

def f(array, n_at_least):
    curr_found_false = 0
    curr_index = 0
    for index, elem in enumerate(array):
        if not elem:
            if curr_found_false == 0:
                curr_index = index
            curr_found_false += 1
            if curr_found_false == n_at_least:
                return curr_index
        else:
            curr_found_false = 0

输出

w=np.array([True,False,True,True,False,False,False])
f(w, 1)
# --> 1
f(w, 3)
# --> 4

答案 2 :(得分:3)

这是一个矢量化解决方案,可以找到零的 islands 的开始,停止索引和长度,最后使用argmax来获得满足零标准的第一个岛的起始索引算是>= n -

def first_occ_index(w, n):
    idx = np.flatnonzero(np.r_[True, w, True])
    lens = np.diff(idx) - 1
    return idx[(lens >= n).argmax()]

示例运行 -

In [107]: w
Out[107]: array([ True, False,  True,  True, False, False, False])

In [108]: first_occ_index(w, n=1)
Out[108]: 1

In [109]: first_occ_index(w, n=3)
Out[109]: 4

答案 3 :(得分:1)

它应该以这种方式工作:

def n_at_least(n):
    for i in range(len(w)):
         if not any(w[i:i+n]):
             return i

但我不知道是否有更好的方法...

答案 4 :(得分:1)

这是使用带切片的生成器表达式的一种方法:

w = np.array([True,False,True,True,False,False,False])

n = 2
val = False

res = next((i for i, j in enumerate(w[k:k+n] for k in range(len(w)-n+1)) \
            if np.all(j==val)), None)

# 4

答案 5 :(得分:1)

我认为对于这种线性搜索操作,python实现是可以的。我的建议如下:

def find_block(arr, n_at_least=1):
    current_index = 0
    current_count = 0
    for index, item in enumerate(arr):
         if item:
             current_count = 0
             current_index = index + 1
         else:
             current_count += 1
         if current_count == n_at_least:
             return current_index
         return None

运行此功能会产生以下输出:

>>> import numpy
>>> w = numpy.array([True, False, True, True, False, False, False])
>>> find_block(w, n_at_least=1)
1
>>> find_block(w, n_at_least=3)
4
>>> find_block(w, n_at_least=4)
>>> # None