我已经根据我的需要调整了这里的滑动窗口生成器函数( 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/