রোলিং বা স্লাইডিং উইন্ডো পুনরুক্তি?


150

আমার একটি ক্রম / পুনরুক্তি / জেনারেটরের উপরে পুনরাবৃত্তিযোগ্য একটি রোলিং উইন্ডো (ওরফে স্লাইডিং উইন্ডো) দরকার। ডিফল্ট পাইথন পুনরাবৃত্তি একটি বিশেষ কেস হিসাবে বিবেচনা করা যেতে পারে, যেখানে উইন্ডোর দৈর্ঘ্য ১. আমি বর্তমানে নিম্নলিখিত কোডটি ব্যবহার করছি। কারও কি আরও বেশি পাইথোনিক, কম ভার্বোস, বা এটি করার জন্য আরও কার্যকর পদ্ধতি আছে?

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()) এটি মনে রাখা উচিত যে স্থির সময়ে প্রতিটি উইন্ডোর জন্য নতুন মান গণনা করার জন্য দক্ষ অ্যালগরিদম রয়েছে (উইন্ডোর আকার নির্বিশেষে)। আমি পাইথন লাইব্রেরিতে এই কয়েকটি অ্যালগরিদম একসাথে সংগ্রহ করেছি: ঘূর্ণায়মান
অ্যালেক্স রিলে

উত্তর:


123

পাইথন ডক্সের একটি পুরানো সংস্করণে itertoolsউদাহরণ সহ রয়েছে :

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 হবে? এটি কি আদৌ ডিফল্ট হওয়া উচিত?
সিঙ্গেলাইজেশন ইলিমিনেশন

19
@ টেকেনম্যাকগুয়ে: আমি এই রেসিপিটির যুক্তিটির লেখক কী তা জানি না, তবে আমি ২ টিও বেছে নেব 2 পূর্ববর্তী (বা পরবর্তী) আইটেমটি জানতে হবে, অন্য কোনও নির্দিষ্ট এন এর চেয়ে যুক্তিযুক্তভাবে বেশি।
kindall

27
এই উদাহরণটি ডক্স থেকে কেন সরানো হয়েছে তা কি কেউ জানেন? এটিতে কোনও সমস্যা ছিল নাকি এখন এর চেয়ে সহজ বিকল্প আছে?
wim

12
উদাহরণটি অপসারণ সম্পর্কে কৌতূহল পেয়েছিলেন এবং ২het অক্টোবর, ২০০৩-তে প্রতিশ্রুতিবদ্ধ রেটটিঙ্গারটি
দ্বিতীয়

2
কেউ কখন for elem in itলুপে প্রবেশ করবে ?
গ্লাসজায়েদ

47

এটি collections.dequeআপনার জন্য মূলত একটি ফিফো (এক প্রান্তে যুক্ত করুন, অন্য প্রান্তটি থেকে সরিয়ে নিন) যেহেতু এটি একটির জন্য উপযুক্ত বলে মনে হচ্ছে । যাইহোক, আপনি যদি একটি ব্যবহার করেন তবে আপনার listদু'বার কাটা উচিত নয়; পরিবর্তে, আপনি সম্ভবত pop(0)তালিকা এবং append()নতুন আইটেম থেকে করা উচিত ।

আপনার আসলটির পরে নকশাকৃত একটি অনুকূলিত ডিউক-ভিত্তিক বাস্তবায়ন এখানে দেওয়া হয়েছে:

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সংস্করণ এটিকে বড় পুনরাবৃত্ত এবং ছোট উইন্ডোর জন্য প্রহার করে । বড় উইন্ডোগুলিতে, dequeকাঁচা গতিতে আবার টান দেয়।

dequeতালিকা বা টিপলসের তুলনায় স্বতন্ত্র আইটেমগুলিতে অ্যাক্সেস দ্রুত বা ধীর হতে পারে। (শুরুতে থাকা আইটেমগুলি দ্রুত হয়, বা আপনি যদি নেতিবাচক সূচক ব্যবহার করেন তবে শেষের আইটেমগুলি)) আমি sum(w)আমার লুপের শরীরে একটি রাখি; এটি ডেকের শক্তিতে খেলবে (এক আইটেম থেকে পরের দিকে পুনরুক্তি করা দ্রুত, সুতরাং এই লুপটি দ্রুততম পদ্ধতির, পিলমুনচারের চেয়ে 20% দ্রুত প্রসারিত হয়েছিল)। আমি যখন এটিকে আলাদা আলাদাভাবে দশটির একটি উইন্ডোতে সন্ধান করতে এবং আইটেমগুলিতে যুক্ত করি তখন টেবিলগুলি ঘুরিয়ে দেওয়া হয় এবং teeপদ্ধতিটি 20% দ্রুত ছিল। সংযোজনে শেষ পাঁচটি শর্তের জন্য আমি নেতিবাচক সূচী ব্যবহার করে কিছু গতি পুনরুদ্ধার করতে সক্ষম হয়েছি তবে teeএখনও কিছুটা দ্রুত ছিলাম। সামগ্রিকভাবে আমি অনুমান করব যে কোনও একটি বেশিরভাগ ব্যবহারের জন্য যথেষ্ট দ্রুত এবং যদি আপনার আরও কিছুটা পারফরম্যান্স প্রয়োজন হয়, প্রোফাইল এবং সবচেয়ে ভাল কাজ করে এমন একটি চয়ন করুন।


11
yield winহওয়া উচিত yield tuple(win)বা yield list(win)একই dequeঅবজেক্টের রেফারেন্সগুলির পুনরাবৃত্তি ফেরানো রোধ করা উচিত ।
জোয়েল করনেট

1
আমি এটি পিপিআইতে জমা দিয়েছি । সাথে ইনস্টল করুন pip install sliding_window, এবং দিয়ে চালান from sliding_window import window
টমাস লেভিন

1
আপনি যদি list(window(range(10)))[[0,1], [1,2], [2,3], ...] এর মতো কিছু তৈরি করতে চান তবে আপনি একটি শক হয়ে
পল

1
এটা অবশ্যই হবে না; আপনার মতো কিছু করা দরকার list(list(x) for x in window(range(10)))বা অন্যথায় এটির পুনরুক্তকারীতে যুক্ত করুন। কিছু অ্যাপ্লিকেশনগুলির জন্য এটি গুরুত্বপূর্ণ হবে, অন্যদের জন্য নয় এবং যেহেতু আমি গতিতে যাচ্ছিলাম আমি নির্বাচিত না করে এবং প্রয়োজনে উইন্ডোটি অনুলিপি করার জন্য কলারের উপরে অন্স লাগিয়েছি।
কিন্ডেল করুন

1
আপনি যদি tuple()উত্পাদনের আগে প্রয়োজনীয়টি যোগ করেন তবে এই পদ্ধতির অন্যদের চেয়ে কোনও সুবিধা নেই।
কাওয়িং-চিউ

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পরীক্ষাগুলি থেকে, এটি ড্যানিয়েল ডিপাওলো (প্রায় 2: 1 অনুপাত দ্বারা) এর চেয়ে অনেক ধীর এবং খুব বেশি "ভাল" বোধ করে না।
ডেভিড বি

@ ডেভিড বি: আমার বাক্সে এটি ড্যানিয়েল ডিপাওলো-র তুলনায় প্রায় 8% ধীর।
পিলমুনচার

@পিলমুনচার: পাইথন 2.7 বা 3.x? আমি ব্যবহার করছিলাম 2.7। অনুপাতটি মানটির ক্ষেত্রেও মোটামুটি সংবেদনশীল size। আপনি যদি এটি বৃদ্ধি করেন (যেমন, যদি পুনরাবৃত্তিযোগ্য 100000 উপাদান দীর্ঘ হয় তবে উইন্ডোর আকার 1000 করুন), আপনি কোনও বৃদ্ধি দেখতে পাবেন।
ডেভিড বি

2
@ ডেভিড বি: আপনি যা বলছেন তা বোধগম্য। আমার কোডে সেটআপের সময়টি itersহ'ল (আকার!), এবং next()বহুবার কল করা (ইন izip()) সম্ভবত দু'বার টুপল অনুলিপি করার চেয়ে অনেক বেশি সময় ব্যয় করে। আমি পাইথন 2.6.5, বিটিডাব্লু ব্যবহার করছিলাম।
পিলমুনচার

@ পিলমুনচার: আপনার মানে, itersও (আকার ^ 2) এর জন্য সেটআপের সময় ঠিক আছে?
ডেভিড বি

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প্যারামিটারের ব্যবহারের ক্ষেত্রে উদাহরণের জন্য , পাইথনটিতে দক্ষতার সাথে একটি বড় .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=3list(more_itertools.windowed(range(6), 3))
ওপির

10

শুধু একটি দ্রুত অবদান।

যেহেতু বর্তমান পাইথন ডক্সের ইটারটোল উদাহরণগুলিতে "উইন্ডো" নেই (যেমন, 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)

মূলত, আমরা কাটা পুনরাবৃত্তকারীগুলির একটি সিরিজ তৈরি করি, যার প্রত্যেকটিতে একটি প্রারম্ভিক বিন্দু আরও এক ধাপ এগিয়ে। তারপরে, আমরা এগুলি একসাথে জিপ করি। দ্রষ্টব্য, এই ফাংশনটি একটি জেনারেটর দেয় (এটি সরাসরি কোনও জেনারেটর নয়)।

উপরোক্ত সংযোজন-উপাদান এবং অ্যাডভান্সিং-পুনরুক্তি সংস্করণগুলির মতো, কর্মক্ষমতা (অর্থাত্ সর্বোত্তম) তালিকা আকার এবং উইন্ডো আকারের সাথে পরিবর্তিত হয়। আমি এটি পছন্দ করি কারণ এটি দ্বি-লাইনার (এটি ওয়ান-লাইনার হতে পারে, তবে আমি নামকরণের ধারণাগুলি পছন্দ করি)।

দেখা যাচ্ছে যে উপরের কোডটি ভুল । এটি কাজ করে যদি পুনরাবৃত্তিযোগ্য পরামিতিটি একটি ক্রম হয় তবে এটি যদি পুনরুক্তি হয় তবে তা নয়। যদি এটি একটি পুনরাবৃত্তিকারী হয় তবে একই পুনরুক্তিটি আইলিস কলগুলির মধ্যে ভাগ করা হবে (তবে টিড নয়) এবং এটি জিনিসগুলিকে খারাপভাবে ভেঙে দেয়।

এখানে কিছু স্থির কোড রয়েছে:

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 + 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 - 1iterators। consumeপ্রতিটি আয়রেটরকে মোড়ানোর পরিবর্তে ব্যবহার করা isliceপ্রান্তিকভাবে দ্রুত (যথেষ্ট পরিমাণে বৃহত পুনরাবৃত্তির জন্য) যেহেতু আপনি কেবল পর্বের isliceসময় মোড়কের ওভারহেড প্রদান করেন consume, প্রতিটি উইন্ডো-এডিড মান বের করার প্রক্রিয়া চলাকালীন নয় (যাতে এটি আবদ্ধ হয় n, আইটেমের সংখ্যা নয়) iterable)।

পারফরম্যান্স-ভিত্তিক, অন্য কয়েকটি সমাধানের তুলনায়, এটি বেশ ভাল (এবং এটির আঁশ হিসাবে পরীক্ষিত অন্যান্য সমাধানগুলির চেয়ে ভাল)। ipython %timeitম্যাজিক ব্যবহার করে পাইথন 3.5.0.0, লিনাক্স x86-64 এ পরীক্ষিত ।

কিন্ডাল এর dequeসমাধান , isliceহোম-রোলড জেনারেটর এক্সপ্রেশন পরিবর্তে ব্যবহার করে ফলাফলের দৈর্ঘ্য পরীক্ষা করে পারফরম্যান্স / নির্ভুলতার জন্য টুইট করা হয়েছে যাতে উইন্ডোটির চেয়ে বারে বারে ছোট হওয়ার maxlenসাথে সাথে dequeঅবস্থানের পরিবর্তে স্থায়ীভাবে পাস করার ফলে ফল পাওয়া যায় না well কীওয়ার্ড দ্বারা (ছোট ইনপুটগুলির জন্য একটি আশ্চর্যজনক পার্থক্য তৈরি করে):

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

পূর্ববর্তী অভিযোজিত কিন্ডাল সমাধান হিসাবে একই, তবে প্রতিটি 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ব্যবহার করে, তাই প্রদত্ত যে কোনও teeপুনরাবৃত্তিকে teeকেবল একবার উন্নত করা হয়, স্বতঃস্ফূর্তভাবে ক্রমবর্ধমান সংখ্যক বার গ্রাস করা হয় না, মিঃডিআরফেনারের উত্তরটির অনুরূপ অন- ইনলাইনডের অনুরূপ) consumeএবং consumeসমস্ত পরীক্ষার অন্তর্ভুক্তের চেয়ে ধীর গতির , তাই আমি বংশবৃদ্ধির জন্য ফলাফলগুলি বাদ দিয়েছি)।

যেমন আপনি দেখতে পাচ্ছেন, যদি আপনি কলারের ফলাফল সংরক্ষণের প্রয়োজনীয়তার বিষয়ে চিন্তা না করেন তবে কান্ডাল এর সমাধানের আমার অনুকূলিত সংস্করণটি বেশিরভাগ সময় "consume বিজয়ী , ছোট উইন্ডো আকারের কেস" ব্যতীত জিতবে (যেখানে ইনলাইনড জেতা ); এটি পুনরাবৃত্ত আকারে বাড়ার সাথে সাথে তা দ্রুত হ্রাস পায়, উইন্ডোর আকার বাড়ার সাথে সাথে একেবারে অবনতি হয় না (প্রতিটি অন্যান্য সমাধান পুনরাবৃত্ত আকারের বৃদ্ধির জন্য আরও ধীরে ধীরে অবনমিত হয়, তবে উইন্ডোর আকার বৃদ্ধির জন্যও অবনমিত হয়)। এমনকি এটি " map(tuple, ...)আবশ্যকভাবে টিউপলস" কেসটি গুটিয়ে রাখার জন্যও রূপান্তর করা যেতে পারে , যা ফাংশনটিতে টিপলিংটি রাখার চেয়ে সামান্য ধীর হয়ে যায় তবে এটি তুচ্ছ (১-৫% বেশি সময় নেয়) এবং আপনাকে দ্রুত চলার নমনীয়তা রাখতে দেয় যখন আপনি বার বার একই মান ফিরিয়ে সহ্য করতে পারেন।

আপনার যদি রিটার্নগুলি সংরক্ষণের বিরুদ্ধে সুরক্ষার প্রয়োজন consumeহয় তবে ছোট ইনপুট মাপগুলি ব্যতীত ইনলাইন বিজয়গুলি (অ-ইনলাইনড consumeকিছুটা ধীর হলেও একইভাবে স্কেলিং সহ)। deque& Tupling ভিত্তিক সমাধান জয়ী শুধুমাত্র ক্ষুদ্রতম ইনপুট ছোট সেটআপ খরচ কারণে জন্য, এবং লাভ ছোট; এটি খারাপভাবে হ্রাস পায় কারণ পুনরাবৃত্তিযোগ্য দীর্ঘ হয়।

রেকর্ড, kindall এর সমাধান যে অভিযোজিত সংস্করণের জন্য yieldগুলি tupleগুলি আমি ব্যবহার ছিল:

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ক্ষেত্রে সন্নিবেশ করানোর বিষয়টি বিবেচনা করব । তবে যদি পারফরম্যান্সটিকে কোনও সমস্যা হিসাবে দেখানো না হয় তবে আমি পৃথক সংজ্ঞা রাখি; নামযুক্ত ফাংশনটি অপারেশনটিকে কম যাদু / স্ব-ডকুমেন্টিং করে। consumewindowconsumeconsume
শ্যাডোর্যাঙ্গার

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)কল is এটি যদি sequenceকোনও পুনরুক্তি বা জেনারেটর হয় তবে এটি কাজ করবে না । যখন ইনপুটটি মেমরির সাথে খাপ খায়, এটি পুনরাবৃত্তকারীদের চেয়ে আরও বেশি পঠনযোগ্য সমাধান দেয়।
ডেভিড বি

হ্যাঁ আপনি ঠিক. এই বিশেষ কেসটি মূলত ডিএনএ সিকোয়েন্সগুলি স্ক্যান করার জন্য বোঝানো হয়েছিল যা সাধারণত স্ট্রিং হিসাবে উপস্থাপিত হয়। এটি অবশ্যই আপনার উল্লেখ সীমাবদ্ধতা আছে। আপনি যদি চান তবে প্রতিটি স্লাইসের সঠিক দৈর্ঘ্যটি নিশ্চিত করার জন্য কেবল পরীক্ষা করতে পারেন এবং তারপরে পুরো ক্রমটির দৈর্ঘ্য জানতে ভুলে যেতে পারেন। তবে এটি কিছুটা ওভারহেড যুক্ত করবে (প্রতিটি পুনরাবৃত্তিতে একটি লেন () পরীক্ষা)।
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খারাপ প্যাটার্ন বলে মনে করে ?
দু'হাইম

5

সত্যিকারের ঘূর্ণায়মান উইন্ডোটি তৈরি করার জন্য ডেক উইন্ডোর একটি সামান্য পরিবর্তিত সংস্করণ। যাতে এটি মাত্র একটি উপাদান দিয়ে জনবহুল হতে শুরু করে, তারপরে এটি সর্বাধিক উইন্ডো আকারে বৃদ্ধি পায় এবং তার বাম প্রান্তটি শেষের কাছাকাছি আসার সাথে সাথে সঙ্কুচিত হয়:

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)

এটি পাইথন ডকের নথিভুক্ত । আপনি এটিকে সহজেই প্রশস্ত উইন্ডোতে প্রসারিত করতে পারেন।


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ক্রমটি শেষ হয়ে গেলে উত্থাপিত হয় এবং কিছু শীতল কারণেই যা আমার বাইরে।

যাইহোক, এটি সর্বনিম্ন-লাইন সমাধান যাঁর কেবলমাত্র প্রয়োজন হ'ল @ ডানসালমোর সমাধানটি seqকার্যকর হয় __iter__বা __getitem__হয় না itertoolsবা নির্ভর করে না collections:)


দ্রষ্টব্য: স্তম্ভিত পদক্ষেপটি হ'ল (n ^ 2) যেখানে এন উইন্ডোর আকার এবং কেবল প্রথম কলটিতে ঘটে। এটি ও (এন) এর কাছে অপ্টিমাইজ করা যেতে পারে তবে কোডটি কিছুটা
মেসওয়্যার করে তুলবে

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
জর্জি

@ জর্জি আমার মনে হয় আমি উত্তরটি এড়িয়ে গেছি কারণ এটি পাইথন 2 এ লেখা হয়েছিল তবে আমি সম্মত, এটি মূলত একই!
রায়ান কোড্রাই

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

@ কেওক্রোক জিপ (* টি) এর অর্থ কী? এই জাতীয় বিবৃতিতে আমি কোথায় কিছু ডকুমেন্টেশন পেতে পারি?
শেজো 284

1
পাইথন ২.7: ডকস.পিথন.আর. / / লিবারি / ফাংশনস html # zip , তারা তালিকাটি প্যাক করে এবং পৃথক উপাদানগুলিকে জিপ ( আনপ্যাকিং যুক্তি ) হিসাবে ইনপুট হিসাবে সরবরাহ করে
কেওক্রো

0

এটি একটি পুরানো প্রশ্ন তবে যারা এখনও আগ্রহী তাদের জন্য এই পৃষ্ঠায় জেনারেটর ব্যবহার করে একটি উইন্ডো স্লাইডারের দুর্দান্ত বাস্তবায়ন রয়েছে (অ্যাড্রিয়ান রোজব্রোক দ্বারা)।

এটি ওপেনসিভির একটি বাস্তবায়ন তবে আপনি এটি অন্য যে কোনও উদ্দেশ্যে সহজেই ব্যবহার করতে পারেন। আগ্রহী ব্যক্তিদের জন্য আমি কোডটি এখানে পেস্ট করব তবে এটি আরও ভালভাবে বুঝতে আমি মূল পৃষ্ঠাটি দেখার পরামর্শ দিই।

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

স্বেচ্ছাসেবী পূরণ এবং পরিবর্তনশীল পদক্ষেপের আকারের অনুমতি দেওয়ার জন্য ডিপাওলোর উত্তর পরিবর্তিত হয়েছে

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

এখানে একটি ওলাইনার আমি এটি টাইম করেছিলাম এবং এটি শীর্ষ উত্তরের পারফরম্যান্সের সাথে তুলনামূলক এবং লেন (সিক) = 20 এবং ধীরে ধীরে লেন (সিক) = 10000 সহ 20% ধীরে ধীরে 20% থেকে ধীরে ধীরে বড় সিকের সাথে ধীরে ধীরে উন্নত হয়

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

আপনার উত্তর সহ কিছু ব্যাখ্যামূলক পাঠ যুক্ত করুন। এই থ্রেড জুড়ে যে কেউ হোঁচট খাচ্ছে তারা পাইথন নিনজা নয়।
অভিজিৎ সরকার

এটি ২ দ্বারা বন্ধ রয়েছে, এটি কাজ করে: জিপ (* [সেক [i: (লেন (সিক)) - এন + 1 + আই)] আই ইন রেঞ্জ (এন)])
গস্টা ফোর্সাম

0

আইলিস ব্যবহার করে আমার অংশ, সহজ, এক লাইনার, পাইথোনিক উপায়ে চেষ্টা করছি। তবে, সর্বোত্তমভাবে দক্ষ নাও হতে পারে।

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

ব্যাখ্যা: উইন্ডো_ সাইজের আইসিস ব্যবহার করে উইন্ডো তৈরি করুন এবং সমস্ত অ্যারেতে মানচিত্র ব্যবহার করে এই ক্রিয়াকলাপটি পুনরাবৃত্তি করুন।


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.