如何调整滑动窗口的滑动步长?

3

我正在尝试调整滑动窗口在滑动时的距离。我看到SO(stackoverflow)上有很多关于滑动窗口的帖子,但是我似乎找不到一个解释如何调整滑动窗口滑动距离的帖子。我也不一定只是对分块或者调整窗口大小感兴趣(1,2)。

举个例子,如果我有一个由6个字符组成的字符串:

seq = 'ATCGAC'

如果我将窗口大小设置为1,并希望每个步骤窗口滑动2个字符。 我想要以下输出:
期望输出:
['A', 'C', 'A']

另一个例子,如果我有相同的字符串,并想将窗口大小设置为3并且窗口每次滑动3个字符。我希望得到以下输出:

期望输出:

['ATC', 'GAC']

作为最后一个例子,考虑具有长字符串的窗口大小。使用滑动窗口大小为3,并将滑块调整为每次滑动6个字符:
seq = 'ATCGACATCGACATCGAC'

期望输出:

['ATC', 'ATC', 'ATC']

答案实际上就在标题中。从您的第二个链接所接受的答案中,您只需要更改range函数的step参数即可... - Tomerikoo
3个回答

2

我相信有更优雅的解决方案。每当我发现自己使用 range(len(some_iterable)) 时,我感到有点不舒服。

话虽如此,你可以通过一个简单的生成器来实现这个目标。

def window(s: str, size: int, slide_amount: int):
    str_len = len(s)
    for i in range(0, str_len, slide_amount):
        # make sure nothing is yielded smaller than
        # the desired size
        if i + size <= str_len:
            yield s[i:i + size]

print([i for i in window('ATCGAC', 1, 2)]) # ['A', 'C', 'A']
print([i for i in window('ATCGAC', 3, 3)]) # ['ATC', 'GAC']
print([i for i in window('ATCGACATCGACATCGAC', 3, 6)]) # ['ATC', 'ATC', 'ATC']

作为生成器表达式的函数包装器,也可以这样实现。
def window(s: str, size: int, slide_amount: int):
    return (
        s[i:i + size] 
        for i in range(0, len(s), slide_amount) 
        if i + size <= len(s)
    )

这可以轻松地修改为返回一个 list

def window(s: str, size: int, slide_amount: int):
    return [
        s[i:i + size] 
        for i in range(0, len(s), slide_amount) 
        if i + size <= len(s)
    ]

1
您所描述的并不是滑动窗口,而只是切片操作。根据每N个字符拆分字符串?,我们可以编写一个通用的函数进行简单设置:
def custom_slice(iterable, size, step, start=0):
    return [iterable[i:i+size] for i in range(start, len(iterable)-size+1, step)]

以下是一些例子:

>>>custom_slice('ATCGAC', 1, 2)
['A', 'C', 'A']
>>> custom_slice('ATCGAC', 3, 3)
['ATC', 'GAC']
>>> custom_slice('ATCGACATCGACATCGAC', 3, 6)
['ATC', 'ATC', 'ATC']
>>> custom_slice([1, 2, 3, 4, 5, 6, 7, 8], 2, 4)
[[1, 2], [5, 6]]
>>> custom_slice('ATCGAC', 3, 1)  # that's actually a sliding window
['ATC', 'TCG', 'CGA', 'GAC']

我猜你很难找到解决方案,因为在这些问题/答案中,大多数都使用了一个n变量来表示大小和步长。而我们之所以将它们分成两个不同的变量,是为了更好地控制“窗口”。


切片和滑动窗口有什么区别?我只是不确定什么定义了一个滑动窗口作为滑动窗口?这些切片之间需要有重叠吗? - neuron
例如,参见滑动窗口算法是什么?有哪些例子?。从技术上讲,滑动窗口通常会重叠。当然,这只是技术上的问题,我认为它可能会妨碍你寻找/理解解决方案。你发布的第一个链接对于你所需的内容来说过于复杂了,因为它在迭代器上实现了一个滑动窗口,即不能向前或向后查看。当处理字符串时,你没有这些限制要求... - Tomerikoo
我明白你的意思。在我的问题中,我只是想找到一种调整滑动窗口移动距离的方法。如果我知道滑动窗口通常重叠,我会以此为基础来举例说明。 - neuron
无论如何,感谢您的澄清。我现在对此有了更好的理解。感谢您的帮助。 - neuron
1
@neuron 在我看来,滑动窗口并不是直接关于重叠的问题,而是关于在窗口中跟踪某些信息(比如每个字符的计数),并在滑动窗口时只更新这些信息。而不是为每个窗口位置从头重新计算这些信息。当然,这只有在存在重叠的情况下才有意义。 - Kelly Bundy

0
你可以在一个while循环中对字符串进行切片。这不是一个滑动窗口。
seq = 'ATCGAC'
def get_slices(seq, window, slide):
    result = []
    index = 0
    while(index < len(seq)):
        result.append(seq[index: index+window])
        index += slide
    return result 
print(get_slices(seq, 1, 2))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接