Numpy 发现间隔至少有 k 个点

pin*_*hio 7 python numpy scipy

我在间隔中有一些点 [0,20]

我有一个window_size=3可以在上述间隔内移动的大小窗口。因此窗口的开始 - 让我们调用start被限制为[0,17].

假设我们在points下面有一些:

points = [1.4,1.8,   11.3,11.8,12.3,13.2,  18.2,18.3,18.4,18.5]
Run Code Online (Sandbox Code Playgroud)

如果我们想要最少的min_points=4点数,则窗口的起始范围(我手动找到的)的解决方案是:

suitable_starts = [[10.2,11.3],[15.5,17.0]]
Run Code Online (Sandbox Code Playgroud)

即大小3窗口的开始可以是 from 10.2to11.3和 from 15.5to 17.0简单地说+3,窗口的相应结束将只是开始范围

我在寻找一种方式来巧妙的算法覆盖这个快速numpyscipy或其他功能。

我正在寻找的一般功能是:

get_start_windows(interval = [0,20],
    window_size = 3.0, 
    points = [1.4,1.8,11.3,11.8,12.3,13.2,18.2,18.3,18.4,18.5],
    min_points = 4

    return suitable_starts # suitable_starts = [[10.2,11.3],[15.5,17.0]]
Run Code Online (Sandbox Code Playgroud)

笔记:

正如评论中的某人指出的那样,有时当点与 window_size 完全分开时,会出现特殊情况。然而,实际上这些点是双浮点数,它们不可能将 window_size 完全分开,因此可以忽略它们。

这些特殊的例子包括:

points = [1.4,1.8,  11.3,11.8,12.3,13.2,14.2,15.2,16.2,17.2,18.2,18.3,18.4,18.5]
Run Code Online (Sandbox Code Playgroud)

但这些可以安全地忽略。

小智 2

经过一番挣扎,我想出了这个解决方案。

首先是一些解释和想法顺序:

  • 理想情况下,我们希望设置一个窗口大小,并将其从最左边的可接受点滑动到最右边的可接受点,并在min_points位于窗口内时开始计数,并在min_points不再位于窗口内时完成计数(将其想象为痉挛操作器或所以)
  • 基本的陷阱是我们想要离散滑动,所以这里的技巧是仅检查当点的数量可以低于或高于 时min_points,这意味着每次出现元素或window_size低于它时(如所optional_starts反映的)
  • 然后迭代optional_starts并采样第一次满足条件的时间,以及每个时间间隔满足条件的最后一次

所以按照上面的描述写了下面的代码:

def consist_at_least(start, points, min_points, window_size):
    a = [point for point in points if start <= point <= start + window_size]
    return len(a)>=min_points
    


points = [1.4,1.8,   11.3,11.8,12.3,13.2,  18.2,18.3,18.4,18.5]
min_points = 4
window_size = 3
total_interval = [0,20]
optional_starts = points + [item-window_size for item in points if item-window_size>=total_interval[0]] + [total_interval[0] + window_size] + [total_interval[1] - window_size] + [total_interval[0]]
optional_starts = [item for item in optional_starts if item<=total_interval[1]-window_size]
intervals = []
potential_ends = []
for start in sorted(optional_starts):
    is_start_interval = len(intervals)%2 == 0
    if consist_at_least(start, points, min_points, window_size):
        if is_start_interval:
            intervals.append(start)
        else:
            potential_ends.append(start)
    elif len(potential_ends)>0 :
        intervals.append(potential_ends[-1])
        potential_ends = []
if len(potential_ends)>0:
    intervals.append(potential_ends[-1])

print(intervals)
Run Code Online (Sandbox Code Playgroud)

输出:

[10.2, 11.3, 15.5, 17]
Run Code Online (Sandbox Code Playgroud)

每 2 个连续元素反映间隔的开始和结束