为了账号安全,请及时绑定邮箱和手机立即绑定

滚动窗口迭代器还是滑动窗口迭代器?

滚动窗口迭代器还是滑动窗口迭代器?

隔江千里 2019-05-31 13:09:51
滚动窗口迭代器还是滑动窗口迭代器?我需要一个滚动窗口(也称滑动窗口),可以在序列/迭代器/生成器上迭代。默认Python迭代可以被看作是一个特例,其中窗口长度为1。我目前正在使用以下代码。有没有人有更多的毕达通,更少的冗长,或更有效的方法来做这件事?def rolling_window(seq, window_size):     it = iter(seq)     win = [it.next() for cnt in xrange(window_size)] # First window     yield win    for e in it: # Subsequent windows         win[:-1] = win[1:]         win[-1] = e        yield winif __name__=="__main__":     for w in rolling_window(xrange(6), 3):         print w"""Example output:    [0, 1, 2]    [1, 2, 3]    [2, 3, 4]    [3, 4, 5] """
查看完整描述

4 回答

?
翻过高山走不出你

TA贡献1875条经验 获得超3个赞

在Python文档的旧版本中有一个itertools实例:

from itertools import islicedef window(seq, n=2):
    "Returns a sliding window (of width n) over data from the iterable"
    "   s -> (s0,s1,...s[n-1]), (s1,s2,...,sn), ...                   "
    it = iter(seq)
    result = tuple(islice(it, n))
    if len(result) == n:
        yield result    for elem in it:
        result = result[1:] + (elem,)
        yield result

文档中的一个更简洁一些,并且使用itertools我想会有更大的效果。


查看完整回答
反对 回复 2019-05-31
?
慕容森

TA贡献1853条经验 获得超18个赞

这似乎是为一个人量身定做的。collections.deque因为您基本上有一个FIFO(添加到一端,从另一端删除)。但是,即使您使用list你不应该切两次;相反,你应该pop(0)从名单上append()新项目。

下面是一个基于优化的、基于deque的实现,该实现遵循了您的原始实现模式:

from collections import dequedef window(seq, n=2):
    it = iter(seq)
    win = deque((next(it, None) for _ in xrange(n)), maxlen=n)
    yield win
    append = win.append    for e in it:
        append(e)
        yield win

在我的测试中,它轻松地击败了大部分时间张贴在这里的所有其他东西,尽管是Pormuncher的tee对于大型可迭代程序和小窗口,版本优于它。在较大的窗口上,deque再次以原始速度前进。

访问deque可能比列表或元组更快或更慢。(接近开头的项目速度更快,如果使用负索引,则项目接近尾端。)我放了一个sum(w)在我的循环的主体;这发挥了德克的力量(迭代从一个项目到下一个项目是快速的,因此这个循环运行了一个完整的20%的速度比下一个最快的方法当我将其更改为单独查找并在10的窗口中添加项目时,表会翻转,tee方法快20%。我能够恢复一些速度,在添加的最后五个项中使用了负索引,但是tee还是快了一点。总的来说,我估计这两种方法对于大多数用途来说都是足够快的,如果您需要更多的性能,请选择最有效的配置文件。


查看完整回答
反对 回复 2019-05-31
?
蝴蝶不菲

TA贡献1810条经验 获得超4个赞

我喜欢tee():

from itertools import tee, izipdef window(iterable, size):
    iters = tee(iterable, size)
    for i in xrange(1, size):
        for each in iters[i:]:
            next(each, None)
    return izip(*iters)for each in window(xrange(6), 3):
    print list(each)

给予:

[0, 1, 2][1, 2, 3][2, 3, 4][3, 4, 5]


查看完整回答
反对 回复 2019-05-31
  • 4 回答
  • 0 关注
  • 679 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信