【问题标题】:get index of the first block of at least n consecutive False values in boolean array获取布尔数组中至少 n 个连续 False 值的第一个块的索引
【发布时间】:2018-09-16 12:57:15
【问题描述】:

我有一个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 元素的总数,而不是最后一个连续元素的计数。

【问题讨论】:

  • 为什么desired_index=4 a_at_least 是 3 ?
  • @liliscent 我认为n_at_leastFalse 发生所需的次数。所以False连续出现3次的序列的起始索引是4
  • @DavidG 听起来不错。我误解了所有False的最后一个索引。

标签: python numpy boolean cumsum


【解决方案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 # Make sure this is outside for loop

运行此函数会产生以下输出:

>>> 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

【讨论】:

    【解决方案2】:

    这是一个矢量化解决方案,它找到零的开始、停止索引以及 的长度,最后使用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】:

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

      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
      

      【讨论】:

        【解决方案4】:

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

        >>> def first_consec(A, n):
        ...     A = np.r_[True, A, True]
        ...     switch, = np.where(A[:-1]!=A[1:])
        ...     runs = switch[1::2] - switch[::2]
        ...     idx = np.argmax(runs >= n)
        ...     if runs[idx] < n:
        ...         return None
        ...     return switch[2*idx]
        ... 
        >>> first_consec(w, 4)
        >>> first_consec(w, 3)
        4
        >>> first_consec(w, 2)
        4
        >>> first_consec(w, 1)
        1
        

        【讨论】:

          【解决方案5】:

          它应该这样工作:

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

          不过不知道有没有更好的办法……

          【讨论】:

          • 我喜欢它,尽管您不需要 break 并且这个解决方案是 O(n^2)。不过干净。
          【解决方案6】:

          我认为您陷入了只想使用 numpy 函数的 numpy 陷阱。蟒蛇有什么问题?这个解决方案是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
          

          【讨论】:

          • 好答案。但我会声称大多数人都陷入了list“陷阱”:)。 numpy 高效的事实是因为它是第 3 方。
          • @jpp 我想这是真的。但是寻找一个 numpy 解决方案并不总是值得您花时间来获得它带来的好处。话虽这么说,如果有的话我会使用一个。
          • 仅供参考,使用 numpy 和卷积仍然可以更快地完成。见stackoverflow.com/a/62747440/13636407
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-20
          • 1970-01-01
          • 2018-06-06
          相关资源
          最近更新 更多