【问题标题】:How can I extract indices from a numpy array where the size of a contiguous matching section is larger than some minimum?如何从连续匹配部分的大小大于某个最小值的 numpy 数组中提取索引?
【发布时间】:2022-01-07 11:15:18
【问题描述】:

假设我有一些类似的数组

a = np.random.random(100) > 0.5

array([ True,  True, False, False,  True, False, False,  True,  True,
        True, False, False,  True, False,  True, False,  True,  True,
       False, False, False, False, False,  True,...

我想找到相邻Trues 的所有部分的起始索引,至少为X。所以对于上面随机sn-p中的X=3,我想要7。对于X=2,我应该得到0,7,16

我可以用循环来做到这一点,但想知道是否有人能告诉我更聪明的方法?

【问题讨论】:

    标签: python numpy slice


    【解决方案1】:

    试试scipy.signal.find_peaks

    import numpy as np
    from scipy.signal import find_peaks
    
    a = np.array([True, True, False, False, True, False, False, True, True,
                  True, False, False, True, False, True, False, True, True,
                  False, False, False, False, False, True])
    
    _, peaks = find_peaks(np.r_[0, a, 0], width=3)
    result = peaks["left_bases"]
    print(result)
    

    输出

    [7]
    

    对于width=2,你有:

    _, peaks = find_peaks(np.r_[0, a, 0], width=2)
    result = peaks["left_bases"]
    print(result)
    

    输出

    [ 0  7 16]
    

    【讨论】:

    • 感谢您的建议,这个答案对我最有用,因为它还提供了right_bases(我稍后会需要它)。一个问题 - 为什么需要在 a 的开头添加 1
    • @loplateral 其实是零,np.zeros(1) 创建array([0.]),思路是在数组的开头找到峰值,如果有的话。
    • 当然是零!有道理,但实际上我们也需要在末尾添加一个 0 以捕获数组末尾的峰值。即np.r_[0, a, 0]。我实际上对为什么碱基也不需要移动感到困惑,但我从文档中看到它返回“x 中每个峰的左侧和右侧的索引”。
    【解决方案2】:

    您可以使用convolution

    convolution = np.convolve(a, np.array([1, 1, 1]))
    np.where(convolution == 3)[0] - 2
    

    这里的卷积 [1, 1, 1] 会将数字与它之前和之后的数字相加。然后你可以找到所有达到 3 的索引并减去 2

    这里是任意数量连续的概括

    def find_consecutive_sequences(number_of_consecutive, a)
        convolution = np.convolve(a, np.ones(shape=(number_of_consecutive)))
        return np.where(convolution == number_of_consecutive)[0] - (number_of_consecutive - 1 )
    
    print(find_consecutive_sequences(3, a))
    print(find_consecutive_sequences(4, a))
    print(find_consecutive_sequences(5, a))
    

    给了

    [ 7 16 17 18]
    [16 17]
    [16]
    

    对于一个(稍作修改以测试45 的情况)正在

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

    【讨论】:

    • 简洁的方法!但它确实返回重叠,即当我只想要16 时返回1617
    • 确实,如果可以的话,我会使用 scipy 方法,因为它更干净。顺便说一句,您可以删除连续数字以消除重叠。
    【解决方案3】:

    您可以找到连续的Trues,方法是找到布尔数组的累积和,然后将该累积和数组拆分为连续数字的子数组,并提取长度为X的子数组的起点。

    def starting_point_of_X_consecutive_Trues(arr, X):
        arr_cumsum = arr.cumsum()
        splits = np.split(arr_cumsum, np.where(np.diff(arr_cumsum) != 1)[0]+1)
        relevant_points = [splits[0][0]] if len(splits[0]) >= X else []
        relevant_points += [split[1] for split in splits[1:] if len(split)-1 >= X]
        return np.isin(arr_cumsum, relevant_points).nonzero()[0]
    

    输出:

    starting_point_of_X_consecutive_Trues(a, 3) # [7]
    starting_point_of_X_consecutive_Trues(a, 2) # [0,7,16]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-14
      • 1970-01-01
      • 2023-01-25
      • 1970-01-01
      • 2016-12-09
      • 1970-01-01
      • 2022-12-20
      • 1970-01-01
      相关资源
      最近更新 更多