如何从连续匹配部分的大小大于某个最小值的 numpy 数组中提取索引?

How can I extract indices from a numpy array where the size of a contiguous matching section is larger than some minimum?

假设我有一些像

这样的数组
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,...

我想找到最小 X 的相邻 True 的所有部分的起始索引。因此,对于上面随机片段中的 X=3,我想要 7。对于 X=2 我应该得到 0,7,16.

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

尝试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]

你可以使用 convolution :

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

这里的convul​​tion [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])

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

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]