롤링 또는 슬라이딩 윈도우 반복자?


151

시퀀스 / 반복자 / 생성기에서 반복 가능한 롤링 창 (일명 슬라이딩 창)이 필요합니다. 기본 파이썬 반복은 창 길이가 1 인 특별한 경우로 간주 될 수 있습니다. 현재 다음 코드를 사용하고 있습니다. 누구 든지이 작업을 수행하는 데 더 Pythonic, 덜 장황하거나 더 효율적인 방법이 있습니까?

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 win

if __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]
"""

3
반복 할 때 각 창에서 어떤 종류의 작업을 수행하려는 경우 (예 : sum()또는 max()) 일정 시간 (창 크기에 관계없이) 각 창에 대한 새 값을 계산하는 효율적인 알고리즘이 있다는 것을 명심해야합니다 . 파이썬 라이브러리에서 이러한 알고리즘 중 일부를 수집했습니다 : rolling .
Alex Riley

답변:


123

itertools들어 이전 버전의 Python 문서에는 하나가 있습니다 .

from itertools import islice

def 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내가 상상하는 더 큰 효과를 내기 위해 사용 합니다.


2
좋은 대답이지만 (그리고 링크 된 레시피를 재생하는 것을 알고 있습니다) 기본 창 크기가 2가되어야하는 이유가 궁금합니다. 기본값이 있어야합니까?
SingleNegationElimination

19
@TakenMacGuy : 그 레시피의 저자가 무엇인지 모르겠지만, 2를 선택하겠습니다. 2는 가장 유용한 창 크기입니다 (그렇지 않으면 반복하고 창을 필요로하지 않습니다). 이전 (또는 다음) 항목을 알아야 할 필요가있을 것입니다.
kindall

27
이 예제가 문서에서 제거 된 이유를 아는 사람이 있습니까? 그것에 문제가 있었습니까, 아니면 더 쉬운 대안이 있습니까?
wim

12
예제 제거에 대해 궁금해하고 2003 년 10 월 26 일에 rhettinger가 커밋 된
두 번째

2
언제 for elem in it루프에 들어 갈까요?
Glassjawed

47

이것은 collections.deque본질적으로 FIFO를 가지고 있기 때문에 맞춤형으로 보입니다 (한 쪽 끝에 추가하고 다른 쪽에서 제거). 그러나 a를 사용하더라도 list두 번 썰지 않아야합니다. 대신 pop(0)목록과 append()새 항목에서 가져와야합니다.

다음은 원본을 기준으로 패턴 화 된 최적화 된 deque 기반 구현입니다.

from collections import deque

def 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

필자의 테스트에서 필자의 tee버전은 큰 iterables와 작은 창을 위해 그것을 능가 하지만 내 테스트에서 대부분의 시간 동안 여기에 게시 된 다른 모든 것을 능가합니다. 큰 창문에서는 deque원래 속도로 다시 당깁니다.

의 개별 항목에 대한 액세스 deque는 목록 또는 튜플보다 빠르거나 느릴 수 있습니다. (음수 색인을 사용하면 시작 부분 근처의 항목이 빠르거나 끝 부분의 항목이 빠릅니다.) 나는 sum(w)루프의 본문에 넣습니다 . 이것은 deque의 강도에 영향을 미칩니다 (한 항목에서 다음 항목으로의 반복이 빠르기 때문에이 루프는 다음으로 빠른 방법 인 필문 처의 것보다 20 % 빠릅니다). 개별적으로 조회하고 10 개의 창에 항목을 추가하도록 변경하면 테이블이 바뀌고 tee방법이 20 % 빨라졌습니다. 또한 마지막 5 개의 용어에 음수 인덱스를 사용하여 약간의 속도를 회복 할 수 있었지만 tee여전히 조금 더 빠릅니다. 전반적으로 나는 어느 쪽이든 대부분의 사용에 대해 매우 빠르며 약간 더 많은 성능이 필요하다면 프로파일 링하고 가장 적합한 것을 선택하십시오.


11
yield win해야 yield tuple(win)또는 yield list(win)동일한에 대한 참조의 반복자를 반환 방지하기 위해 deque객체입니다.
Joel Cornett

1
나는 이것을 PyPI에 제출 했다 . 함께 설치pip install sliding_window 하고로 실행하십시오 from sliding_window import window.
토마스 레빈

1
당신이 생각하면 충격을 받고 있습니다 list(window(range(10)))[[0,1], [1,2], [2,3], ...]와 같은 것을 생산해야
Paul

1
분명히 그렇지 않습니다. 당신은 같은 것을해야합니다list(list(x) for x in window(range(10)))반복자에 추가하거나 추가해야합니다. 일부 응용 프로그램의 경우 이것은 중요하지 않으며 다른 응용 프로그램에서는 중요하지 않으며 속도를 늦추기 위해 필요하지 않은 경우 창을 복사하도록 호출자를 선택 하지 않았습니다 .
kindall

1
필요한 tuple()수율 을 추가 하기 전에이 방법을 사용하면 다른 방법보다 유리합니다.
kawing-chiu

35

나는 좋아한다 tee():

from itertools import tee, izip

def 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]

나의 빠른 timeit테스트에서, 이것은 Daniel DePaolo의 것 (약 2 : 1 비율)보다 훨씬 느리고 "더 똑똑"하다고 느끼지 않습니다.
David B.

@David B .: 내 상자에서 Daniel DePaolo보다 약 8 % 느립니다.
pillmuncher

@pillmuncher : Python 2.7 또는 3.x? 나는 2.7을 사용하고 있었다. 이 비율은의 값에도 상당히 민감합니다 size. 크기를 늘리면 (예를 들어, iterable의 길이가 100000 개인 경우 창 크기를 1000으로 설정) 증가 할 수 있습니다.
David B.

2
@David B .: 당신의 말이 의미가 있습니다. 내 코드에서 설정 시간 iters은 O (size!)이며 next()여러 번 호출 하는 경우 (in izip()) 튜플을 두 번 복사하는 것보다 시간이 많이 걸립니다. Python 2.6.5, BTW를 사용하고있었습니다.
pillmuncher

@pillmuncher : 설정 시간 iters이 O (size ^ 2)입니까?
David B.

20

여기에 대한 지원을 추가 일반화의 step, fillvalue매개 변수 :

from collections import deque
from itertools import islice

def sliding_window(iterable, size=2, step=1, fillvalue=None):
    if size < 0 or step < 1:
        raise ValueError
    it = iter(iterable)
    q = deque(islice(it, size), maxlen=size)
    if not q:
        return  # empty iterable or size == 0
    q.extend(fillvalue for _ in range(size - len(q)))  # pad to size
    while True:
        yield iter(q)  # iter() to avoid accidental outside modifications
        try:
            q.append(next(it))
        except StopIteration: # Python 3.5 pep 479 support
            return
        q.extend(next(it, fillvalue) for _ in range(step - 1))

필요한 경우 각 청크를 채우는 반복마다 size롤링 step위치 에서 청크 항목을 생성 fillvalue합니다. 예 size=4, step=3, fillvalue='*':

 [a b c d]e f g h i j k l m n o p q r s t u v w x y z
  a b c[d e f g]h i j k l m n o p q r s t u v w x y z
  a b c d e f[g h i j]k l m n o p q r s t u v w x y z
  a b c d e f g h i[j k l m]n o p q r s t u v w x y z
  a b c d e f g h i j k l[m n o p]q r s t u v w x y z
  a b c d e f g h i j k l m n o[p q r s]t u v w x y z
  a b c d e f g h i j k l m n o p q r[s t u v]w x y z
  a b c d e f g h i j k l m n o p q r s t u[v w x y]z
  a b c d e f g h i j k l m n o p q r s t u v w x[y z * *]

step매개 변수 사용 사례의 예는 python에서 큰 .txt 파일을 효율적으로 처리를 참조하십시오 .


17

필요한 것을 정확하게 수행하는 라이브러리가 있습니다.

import more_itertools
list(more_itertools.windowed([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],n=3, step=3))

Out: [(1, 2, 3), (4, 5, 6), (7, 8, 9), (10, 11, 12), (13, 14, 15)]

step=3OP의 요청과 일치하도록 실제로 제거해야합니다.list(more_itertools.windowed(range(6), 3))
user3780389

10

빠른 기여.

현재 파이썬 문서에는 itertool 예제 (예 : http://docs.python.org/library/itertools.html 의 맨 아래)에 "창"이 없으므로 다음은 그룹화 코드를 기반으로하는 스 니펫입니다. 주어진 예 중 하나입니다.

import itertools as it
def window(iterable, size):
    shiftedStarts = [it.islice(iterable, s, None) for s in xrange(size)]
    return it.izip(*shiftedStarts)

기본적으로, 우리는 시작 지점이 한 지점 앞으로 이동하는 일련의 슬라이스 반복자를 만듭니다. 그런 다음 함께 묶습니다. 이 함수는 생성기를 반환합니다 (직접 생성기 자체는 아님).

위의 appending-element 및 advancing-iterator 버전과 마찬가지로 성능 (즉, 최고)은 목록 크기와 창 크기에 따라 다릅니다. 나는 이것이 2 라이너이기 때문에 이것을 좋아합니다 (1 라이너 일 수는 있지만 명명 개념을 선호합니다).

위의 코드가 잘못되었습니다 . 매개 변수가 iterable에 전달되면 작동합니다. 가 시퀀스이지만 하지 않습니다. iterator 호출 인 경우 islice 호출간에 동일한 iterator가 공유되지만 (티는 아님) 이로 인해 상황이 나빠집니다.

다음은 일부 고정 코드입니다.

import itertools as it
def window(iterable, size):
    itrs = it.tee(iterable, size)
    shiftedStarts = [it.islice(anItr, s, None) for s, anItr in enumerate(itrs)]
    return it.izip(*shiftedStarts)

또한 책에 대한 버전이 하나 더 있습니다. 반복자를 복사 한 다음 여러 번 복사하는 대신이 버전은 시작 위치를 앞으로 이동함에 따라 각 반복기의 쌍별 사본을 만듭니다. 따라서, 반복자 t는 t에서 시작점을 갖는 "완전한"반복자와 반복자 t + 1의 기초를 제공합니다.

import itertools as it
def window4(iterable, size):
    complete_itr, incomplete_itr = it.tee(iterable, 2)
    iters = [complete_itr]
    for i in xrange(1, size):
        incomplete_itr.next()
        complete_itr, incomplete_itr = it.tee(incomplete_itr, 2)
        iters.append(complete_itr)
    return it.izip(*iters)

9

itertools레시피 를 결합하는 방법을 보여주기 pairwise위해 window레시피를 사용하여 consume레시피 를 가능한 한 직접 레시피로 다시 확장합니다 .

def consume(iterator, n):
    "Advance the iterator n-steps ahead. If n is none, consume entirely."
    # Use functions that consume iterators at C speed.
    if n is None:
        # feed the entire iterator into a zero-length deque
        collections.deque(iterator, maxlen=0)
    else:
        # advance to the empty slice starting at position n
        next(islice(iterator, n, n), None)

def window(iterable, n=2):
    "s -> (s0, ...,s(n-1)), (s1, ...,sn), (s2, ..., s(n+1)), ..."
    iters = tee(iterable, n)
    # Could use enumerate(islice(iters, 1, None), 1) to avoid consume(it, 0), but that's
    # slower for larger window sizes, while saving only small fixed "noop" cost
    for i, it in enumerate(iters):
        consume(it, i)
    return zip(*iters)

window조리법과 동일 pairwise그것은 단지 두 번째에있는 하나의 요소 "소비"대체 tee점진적에 소비하는 증가에 -ed 반복자를 n - 1반복자. consume각 반복자를 래핑하는 대신 사용 하는 것은 각 윈도우 값을 추출하는 프로세스가 아닌 단계 동안 래핑 오버 헤드 islice만 지불하므로 (반복적으로 큰 반복 가능의 경우) 약간 더 빠릅니다 (따라서 항목 수가 아닌isliceconsumeniterable ).

성능면에서 다른 솔루션과 비교할 때 이것은 상당히 좋습니다 (확장 할 때 테스트 한 다른 솔루션보다 낫습니다). ipython %timeit매직을 사용하여 Python 3.5.0, Linux x86-64에서 테스트되었습니다 .

kindall는의 deque솔루션을 사용하여 성능 / 정확성 불통을 islice대신 집 압연 발전기 표현의와 반복 가능한 창보다 짧은 경우는 결과를 산출하지 않도록 결과 길이를 테스트뿐만 아니라 전달 maxlen의를 deque위치 적으로 대신 키워드 별 (작은 입력의 경우 놀라운 차이를 만듭니다) :

>>> %timeit -r5 deque(windowkindall(range(10), 3), 0)
100000 loops, best of 5: 1.87 μs per loop
>>> %timeit -r5 deque(windowkindall(range(1000), 3), 0)
10000 loops, best of 5: 72.6 μs per loop
>>> %timeit -r5 deque(windowkindall(range(1000), 30), 0)
1000 loops, best of 5: 71.6 μs per loop

이전에 수정 된 kindall 솔루션과 동일하지만 각각이 yield win변경된 것으로 yield tuple(win)생성 된 결과를 저장하면 모든 저장된 결과가 실제로 가장 최근 결과를 보지 않고 (이 시나리오에서는 다른 모든 합리적인 솔루션이 안전함) tuple=tuple함수 정의에 추가 의 사용을 이동 tuple으로부터 BLEGB받는 사람 L:

>>> %timeit -r5 deque(windowkindalltupled(range(10), 3), 0)
100000 loops, best of 5: 3.05 μs per loop
>>> %timeit -r5 deque(windowkindalltupled(range(1000), 3), 0)
10000 loops, best of 5: 207 μs per loop
>>> %timeit -r5 deque(windowkindalltupled(range(1000), 30), 0)
1000 loops, best of 5: 348 μs per loop

consume기반 솔루션 :

>>> %timeit -r5 deque(windowconsume(range(10), 3), 0)
100000 loops, best of 5: 3.92 μs per loop
>>> %timeit -r5 deque(windowconsume(range(1000), 3), 0)
10000 loops, best of 5: 42.8 μs per loop
>>> %timeit -r5 deque(windowconsume(range(1000), 30), 0)
1000 loops, best of 5: 232 μs per loop

동일 consume하지만 런타임을 줄이기 위해 함수 호출 및 테스트 를 피하기위한 인라인 else경우 , 특히 설정 오버 헤드가 작업의 중요한 부분 인 작은 입력의 경우 :consumen is None

>>> %timeit -r5 deque(windowinlineconsume(range(10), 3), 0)
100000 loops, best of 5: 3.57 μs per loop
>>> %timeit -r5 deque(windowinlineconsume(range(1000), 3), 0)
10000 loops, best of 5: 40.9 μs per loop
>>> %timeit -r5 deque(windowinlineconsume(range(1000), 30), 0)
1000 loops, best of 5: 211 μs per loop

(측면 노트 : 중첩 된 객체 를 만들기 위해 기본 인수 2를 반복적으로 pairwise사용 하는 변형입니다 . 따라서 주어진 반복자는 한 번만 진행되고 독립적으로 증가하는 횟수는 소비하지 않습니다. MrDrFenner의 대답 은 인라인이 아닌 것과 유사합니다 모든 테스트 에서 인라인보다 느리 므로 간결하게하기 위해 그 결과를 생략했습니다.)teeteeconsumeconsume

보시다시피 , 발신자가 결과를 저장해야 할 가능성에 대해 신경 쓰지 않는다면, 최적화 된 kindall의 솔루션 버전은 "큰 반복 가능한 작은 창 크기 사례" (인라인 된 consume승자 가 아닌 경우)를 제외하고 대부분의 시간에 승리합니다. ); 반복 가능한 크기가 증가함에 따라 빠르게 저하되는 반면 창 크기가 증가함에 따라 전혀 저하되지 않습니다 (반복 가능한 크기가 증가하면 다른 솔루션은 모두 느리게 저하되지만 창 크기는 증가합니다). 튜플 map(tuple, ...)링 기능보다 약간 느리게 실행 되는을 감싸서 "필요한 튜플"케이스에 맞게 조정할 수도 있지만 사소한 (1-5 % 더 길어짐) 실행 속도를 빠르게 유지할 수 있습니다. 동일한 값을 반복적으로 반환하는 것을 허용 할 수있는 경우

반품 저장에 대해 안전이 필요한 경우, 인라인consume 이 아닌 가장 작은 입력 크기 (인라인 consume이 아닌 것이 약간 느리지 만 비슷한 스케일링)에서 승리합니다 . 그만큼deque및 단지 작은 인해 설치 비용이 최소 입력을위한 기반 솔루션 승 tupling 및 이득이 작다; iterable이 길어질수록 심하게 저하됩니다.

기록 것을 kindall의 솔루션의 적응 버전 yieldtuple의 내가 사용했다 :

def windowkindalltupled(iterable, n=2, tuple=tuple):
    it = iter(iterable)
    win = deque(islice(it, n), n)
    if len(win) < n:
        return
    append = win.append
    yield tuple(win)
    for e in it:
        append(e)
        yield tuple(win)

tuple함수 정의 라인에서 캐싱을 제거 하고 tuple각각 에서 사용 yield하면 더 빠르지 만 덜 안전한 버전을 얻을 수 있습니다.


분명히, 이것은 생각보다 덜 효율적입니다. consume일반 목적 (완료 기능 포함 consume)이므로 추가 가져 오기 및 사용 별 테스트가 필요 n is None합니다. 실제 코드에서 나는 거라고 및 경우에만 경우, 결정의 성능에 문제가 있었다, 또는 정말, 내가 인라인 생각 하는데요 더 간결한 코드를 필요로 else하는 경우 consume에를 window내가 사용하지 않은 가정, consume다른 거. 그러나 성능이 문제가되지 않으면 별도의 정의를 유지합니다. 명명 된 consume함수는 작업을 덜 마술 / 자기 문서화합니다.
ShadowRanger

7

다음 코드를 생성기를 사용하여 가독성을 크게 높이는 간단한 슬라이딩 창으로 사용합니다. 그 속도는 지금까지 내 경험에서 생물 정보학 시퀀스 분석에 사용하기에 충분했습니다.

이 방법이 아직 사용되지 않았으므로 여기에 포함시킵니다. 다시, 나는 비교 성능에 대해 주장하지 않습니다.

def slidingWindow(sequence,winSize,step=1):
"""Returns a generator that will iterate through
the defined chunks of input sequence. Input sequence
must be sliceable."""

    # Verify the inputs
    if not ((type(winSize) == type(0)) and (type(step) == type(0))):
        raise Exception("**ERROR** type(winSize) and type(step) must be int.")
    if step > winSize:
        raise Exception("**ERROR** step must not be larger than winSize.")
    if winSize > len(sequence):
        raise Exception("**ERROR** winSize must not be larger than sequence length.")

    # Pre-compute number of chunks to emit
    numOfChunks = ((len(sequence)-winSize)/step)+1

    # Do the work
    for i in range(0,numOfChunks*step,step):
        yield sequence[i:i+winSize]

3
여기서 가장 큰 단점은 len(sequence)전화입니다. sequence이터레이터 또는 생성기 인 경우 작동하지 않습니다 . 입력이 메모리에 맞으면 반복자보다 더 읽기 쉬운 솔루션을 제공합니다.
David B.

네 말이 맞아. 이 특별한 경우는 원래 일반적으로 문자열로 표시되는 DNA 서열을 스캔하기위한 것입니다. 확실히 당신이 언급 한 제한이 있습니다. 원하는 경우 각 슬라이스를 테스트하여 여전히 올바른 길이인지 확인한 다음 전체 시퀀스의 길이를 알아야하는 것을 잊을 수 있습니다. 그러나 약간 더 많은 오버 헤드 (len () 테스트마다 반복)가 추가됩니다.
Gus

6
def GetShiftingWindows(thelist, size):
    return [ thelist[x:x+size] for x in range( len(thelist) - size + 1 ) ]

>> a = [1, 2, 3, 4, 5]
>> GetShiftingWindows(a, 3)
[ [1, 2, 3], [2, 3, 4], [3, 4, 5] ]

파이썬에서 "range (len")를 보는 순간 코드 냄새입니다.
Mark Lawrence

@MarkLawrence range(len파이썬에서 나쁜 패턴 이라고 생각 하는 것은 무엇입니까 ?
duhaime

5

실제 롤링 창으로 만들기 위해 deque 창의 약간 수정 된 버전. 따라서 하나의 요소로 채워지기 시작한 다음 최대 창 크기로 커지고 왼쪽 가장자리가 끝 부분에 가까워지면 축소됩니다.

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

for wnd in window(range(5), n=3):
    print(list(wnd))

이것은 준다

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

3
def rolling_window(list, degree):
    for i in range(len(list)-degree+1):
        yield [list[i+o] for o in range(degree)]

이것을 롤링 평균 함수로 만들었습니다.


3

왜 안돼

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return zip(a, b)

파이썬 doc에 문서화되어 있습니다. 넓은 창으로 쉽게 확장 할 수 있습니다.


2

여러 반복자!

def window(seq, size, step=1):
    # initialize iterators
    iters = [iter(seq) for i in range(size)]
    # stagger iterators (without yielding)
    [next(iters[i]) for j in range(size) for i in range(-1, -j-1, -1)]
    while(True):
        yield [next(i) for i in iters]
        # next line does nothing for step = 1 (skips iterations for step > 1)
        [next(i) for i in iters for j in range(step-1)]

next(it) 제기 StopIteration 순서가 완료 될 때와 멋진 이유에 대한 그 전체 창을 형성하지 않는 나머지 값을 무시하고 나를 넘어, 여기에 yield 문이 excepts IT와 함수가 반환.

어쨌든,이 그의 유일한 요구 사항 즉 최소 라인 솔루션 아직 seq중 하나를 구현 __iter__하거나 __getitem__및에 의존하지 않는 itertools또는 collections@ dansalmo의 솔루션 외에이 :)


참고 : 스 태거 단계는 O (n ^ 2)이며, 여기서 n은 창의 크기이며 첫 번째 호출에서만 발생합니다. 그것은 O (n)까지 최적화 될 수 있지만 코드를 조금 더
혼란스럽게

2

게으르게하자!

from itertools import islice, tee

def window(iterable, size): 
    iterators = tee(iterable, size) 
    iterators = [islice(iterator, i, None) for i, iterator in enumerate(iterators)]  
    yield from zip(*iterators)

list(window(range(5), 3))
# [(0, 1, 2), (1, 2, 3), (2, 3, 4)]

1
#Importing the numpy library
import numpy as np
arr = np.arange(6) #Sequence
window_size = 3
np.lib.stride_tricks.as_strided(arr, shape= (len(arr) - window_size +1, window_size), 
strides = arr.strides*2)

"""Example output:

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

"" "


3
답변에 대한 텍스트를 작성하십시오.
jrswgtr

1

나는 몇 가지 솔루션과 테스트 한 솔루션을 테스트했으며 내가 찾은 솔루션이 가장 빠르다는 것을 알았으므로 공유 할 것이라고 생각했습니다.

import itertools
import sys

def windowed(l, stride):
    return zip(*[itertools.islice(l, i, sys.maxsize) for i in range(stride)])

1
이 답변의 첫 번째 솔루션과 비슷합니다. stackoverflow.com/a/11249883/7851470
Georgy

@georgy 나는 Python2로 작성 되었기 때문에 그 대답을 건너 뛰었다 고 생각하지만 본질적으로 동일합니다!
Ryan Codrai

0
>>> n, m = 6, 3
>>> k = n - m+1
>>> print ('{}\n'*(k)).format(*[range(i, i+m) for i in xrange(k)])
[0, 1, 2]
[1, 2, 3]
[2, 3, 4]
[3, 4, 5]

0

다음을 사용하는 것은 어떻습니까 :

mylist = [1, 2, 3, 4, 5, 6, 7]

def sliding_window(l, window_size=2):
    if window_size > len(l):
        raise ValueError("Window size must be smaller or equal to the number of elements in the list.")

    t = []
    for i in xrange(0, window_size):
        t.append(l[i:])

    return zip(*t)

print sliding_window(mylist, 3)

산출:

[(1, 2, 3), (2, 3, 4), (3, 4, 5), (4, 5, 6), (5, 6, 7)]

@ keocra zip (* t)은 무엇을 의미합니까? 그런 종류의 진술에 대한 문서는 어디서 찾을 수 있습니까?
Shejo284

1
Python 2.7 : docs.python.org/2/library/functions.html#zip , 별은 목록의 압축을 풀고 개별 요소를 zip ( unpacking arguments )에 대한 입력으로 제공
keocra

0

이것은 오래된 질문이지만 여전히 관심있는 사람들을 위해 생성기를 사용하여 창 슬라이더를 훌륭하게 구현 했습니다. 페이지의 합니다 (Adrian Rosebrock).

OpenCV의 구현이지만 다른 목적으로도 쉽게 사용할 수 있습니다. 열망하는 사람들에게는 여기에 코드를 붙여 넣을 것이지만 더 잘 이해하려면 원래 페이지를 방문하는 것이 좋습니다.

def sliding_window(image, stepSize, windowSize):
    # slide a window across the image
    for y in xrange(0, image.shape[0], stepSize):
        for x in xrange(0, image.shape[1], stepSize):
            # yield the current window
            yield (x, y, image[y:y + windowSize[1], x:x + windowSize[0]])

팁 : 당신은 확인하실 수 있습니다 .shape귀하의 요구 사항을 충족하지 않는 사람들을 무시하는 발전기를 반복 할 때 창을

건배


0

임의의 채우기 및 가변 단계 크기를 허용하도록 수정 된 DiPaolo의 답변

import itertools
def window(seq, n=2,step=1,fill=None,keep=0):
    "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(itertools.islice(it, n))    
    if len(result) == n:
        yield result
    while True:        
#         for elem in it:        
        elem = tuple( next(it, fill) for _ in range(step))
        result = result[step:] + elem        
        if elem[-1] is fill:
            if keep:
                yield result
            break
        yield result

0

여기 하나의 라이너가 있습니다. 시간을내어 최고 답변의 성능과 비교할 수 있으며 len (seq) = 20 일 때 20 % 느리고 len (seq) = 10000 일 때 7 % 느림에서 더 큰 seq로 점진적으로 향상됩니다.

zip(*[seq[i:(len(seq) - n - 1 + i)] for i in range(n)])

답과 함께 설명문을 추가하십시오. 이 글에서 쓰러지는 모든 사람이 Python Ninja는 아닙니다.
Abhijit Sarkar

그것은 2에 의해 꺼져 있습니다, 이것은 작동합니다 : zip (* [seq [i : (len (seq)-n + 1 + i)] in i 범위 (n)])
Gösta Forsum

0

islice를 사용하여 내 부분, 단순, 하나의 라이너, pythonic 방식을 시도합니다. 그러나 효율적이지 않을 수 있습니다.

from itertools import islice
array = range(0, 10)
window_size = 4
map(lambda i: list(islice(array, i, i + window_size)), range(0, len(array) - window_size + 1))
# output = [[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6], [4, 5, 6, 7], [5, 6, 7, 8], [6, 7, 8, 9]]

설명 : window_size의 islice를 사용하여 창을 작성하고 모든 배열에서 map을 사용하여이 조작을 반복하십시오.


0

딥 러닝에서 윈도우 데이터 슬라이딩을위한 최적화 된 기능

def SlidingWindow(X, window_length, stride):
    indexer = np.arange(window_length)[None, :] + stride*np.arange(int(len(X)/stride)-window_length+4)[:, None]
    return X.take(indexer)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.