Rolling or sliding window iterator?

后端 未结 23 1408
南方客
南方客 2020-11-21 05:23

I need a rolling window (aka sliding window) iterable over a sequence/iterator/generator. Default Python iteration can be considered a special case, where the window length

相关标签:
23条回答
  • 2020-11-21 05:51

    Trying my part, simple, one liner, pythonic way using islice. But, may not be optimally efficient.

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

    Explanation: Create window by using islice of window_size and iterate this operation using map over all array.

    0 讨论(0)
  • 2020-11-21 05:52

    Modified DiPaolo's answer to allow arbitrary fill and variable step size

    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 讨论(0)
  • 2020-11-21 05:55

    I like 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)
    

    gives:

    [0, 1, 2]
    [1, 2, 3]
    [2, 3, 4]
    [3, 4, 5]
    
    0 讨论(0)
  • 2020-11-21 05:56
    #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]
    

    """

    0 讨论(0)
  • 2020-11-21 05:57

    I use the following code as a simple sliding window that uses generators to drastically increase readability. Its speed has so far been sufficient for use in bioinformatics sequence analysis in my experience.

    I include it here because I didn't see this method used yet. Again, I make no claims about its compared performance.

    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]
    
    0 讨论(0)
  • 2020-11-21 06:01

    Let's make it lazy!

    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)]
    
    0 讨论(0)
提交回复
热议问题