python - 采用滑动窗口 Python 生成器函数来随机播放窗口

标签 python random generator shuffle sliding-window

我已经根据我的需要调整了这里的滑动窗口生成器函数( https://scipher.wordpress.com/2010/12/02/simple-sliding-window-iterator-in-python/ )。这是我第一次接触生成器函数,所以我做了很多背景阅读。鉴于我的经验(仍然)有限,我正在就以下问题征求建议:

下面的代码执行此操作:我使用滑动窗口函数在大约 250 个字符的窗口中迭代 5,500 个字符的字符串(约 5,500 bp 的 DNA 序列),步长为 1。对于每个 block ,我将其 GC 内容与 750 行文件中的一行进行比较。 (GC含量是等于G或C的字符串元素的百分比)。

但是,对于我的下游使用,我真的很想随机循环这些 block 。从我的堆栈溢出搜索中,我了解到不可能对生成器对象进行洗牌,并且我无法对函数内的窗口进行洗牌,因为它实际上一次搜索一个窗口,然后返回到函数以查找下一个 block ,因为那个“产量”。 (如果我误解了,请纠正我)。

目前,我的代码看起来像这样(当然,使用上面链接中的生成器函数):

with open('/pathtofile/file.txt') as f:
    for line in f:
        line = line.rstrip()
        # For each target, grab target length (7), gc content (8)
        targ_length = line.split("\t")[8]
        gc = int(line.split("\t")[7])
        # Window size = amplicon length minus length of fwd and rev primers
        # Use a sliding window function to go along "my_seq" (5,500bp sequence). Check GC content for each window.
        chunks = slidingWindow(my_seq, targ_length, step=1)
        found = 0
        for i in chunks:
            # When GC content = same as file, save this window as the pos ctrl fragment & add primers to it
            dna_list = list(i)
            gc_count = dna_list.count("G") + dna_list.count("C")
            gc_frac = int((gc_count / len(dna_list)) * 100)
            # if (gc - 5) < gc_frac < (gc + 5):
            if gc_frac == gc:
                found = 1
                # Store this piece
                break
        if found == 0:
            # Store some info to look up later 

有人有最佳方法的想法吗?对我来说,最明显的(也基于 Stack Overflow 搜索)是在没有生成器函数的情况下重写它。我担心在包含大约 5,251 个元素的列表上循环 750 次。我可以做?生成器似乎是我想做的事情的一个优雅的解决方案,除了现在我决定随机化 block 顺序。显然我需要牺牲效率来做到这一点,但我想知道更有经验的程序员是否有一些聪明的解决方案。谢谢!

最佳答案

我相信你是正确的,你不能打乱生成器的输出,但是随机化它实际生成输出的方式相对容易。下面是 slidingWindow 生成器函数的修改版本,它使用 numpy 模块进行随机化(并设置可选种子):

import numpy as np
def slidingWindow(sequence,winSize,step=1, seed=987):
    """Returns a generator that will iterate through
    the defined chunks of input sequence.  Input sequence
    must be iterable."""

    # Verify the inputs
    try:
        it = iter(sequence)
    except TypeError:
        raise Exception("**ERROR** sequence must be iterable.")
    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.")

    # set the seed for the pseudo-random number generator
    np.random.seed(seed)

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

    # Create a shuffled index of start points
    idx = np.arange(numOfChunks)
    np.random.shuffle(idx)

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

然后您可以保持主代码不变,或者修改创建 block 的方式以设置不同的种子:

chunks = slidingWindow(my_seq, targ_length, step=1, seed=987)

关于python - 采用滑动窗口 Python 生成器函数来随机播放窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57435588/

相关文章:

c++ - 简单的数字猜谜游戏。 C++

python - 有效地生成所有小于 N 的合数(及其因式分解)

python - 跨过 yield 语句

python - 如何将 Pymodm 对象转换为 JSON?

python - 单行异常处理

python - Tkinter Text Widget Ctrl+A + DEL 删除标签

python - 如何在 Django 中提供可下载的图像文件

c++ - 括号中的变量 C++

java - 唯一或不重复的随机数生成

Python:生成器失败