我正在阅读格式为
的大型基因文件>GeneID
ACTCTCTCTATATATATATAT\n
GCTCTGCTTCTAGAGAGAGTG\n
TCTATTTGTTTATATATCTTT\n
>GeneID
GCTCTGCTTCTAGAAATTCCC\n
ACTCTGTATATATTTTCAAAA\n
GCTCTGCTTCTAGAGAGAGTG\n
每个基因以>开头。然后是一个唯一的ID。来自该基因的核苷酸后。 不幸的是,生成了这个文件,因此每个序列行之间都有换行符。
我需要在每个序列中读取一个连续的字符串。所以,我一直在使用下一个方法(如下所示)。
for line in filer:
if line.startswith(">"):
# Find Sequences
seq_seg = next(filer)
seq = ""
# Concatenate lines until find next gene
while not (seq_seg.startswith(">")):
seq += seq_seg.strip() # Get rid of '\n'
seq_seg = next(filer)
我发现我的脚本只占用了文件中的一半基因,因为在使while循环失败的条件下调用next时,文件指针指向下一个基因ID,然后在下一次迭代时对于for循环执行,它将移动到下一个文件。
有没有办法将文件指针倒回到前一行,所以我的for循环将其作为新基因捕获?
我见过类似的问题,但没有一个问题涉及我用
阅读文件的具体方式 for line in file:
#do stuff
答案 0 :(得分:3)
我会使用生成器而不是跳过线(有些东西告诉我这可以大大简化):
def parse_file(file):
id = ''
gene = ''
for line in file:
if line.startswith('>'):
if gene:
yield id, gene
id = line[1:]
gene = ''
else:
gene += line.strip()
else:
yield id, gene # Final gene
现在,您可以使用几行代码安全地迭代整个事情:
with open('file.txt', 'r') as handle:
for gene_id, nucleotides in parse_file(handle):
print gene_id, nucleotides
还有pyfasta。
或itertools
的更一般的功能:
def grouper(line):
return line.startswith('>') and line[1:]
def itersplit(it, pred):
groups = (list(group) for key, group in itertools.groupby(it, pred))
yield from zip(groups, groups)
def parse(file):
for key, group in itersplit(file, grouper):
yield key[0], ''.join(group)
答案 1 :(得分:1)
有没有办法将文件指针倒回到前一行,所以我的for循环将其作为新基因捕获?
在Python 3中,没有。您不能将文件迭代与文件指针上的显式操作混合在一起。
在Python 2中,也许吧。但这只是偶然的,这就是它在3.0中被禁止的原因,并不保证在每种情况下都能正常工作。所以,你不应该这样做。
更好的方法是询问如何回放迭代器。答案是itertools
。您可以使用tee
来提前查看。您可以将迭代器重新绑定到chain([pushed_back_value], iterator)
。等等。
但是,正如其他人所指出的那样,有一种更好的方法可以做到这一点。你真的不需要向前看或回到这里,你只需要分组。您也可以使用itertools
执行此操作,但在这种情况下,您可以轻松地执行此操作,就像Blender所示。
答案 2 :(得分:1)
以下是另一种使用re
和mmap
的方法:
import mmap, re
with open(your_file) as fin:
mm = mmap.mmap(fin.fileno(), 0, access=mmap.ACCESS_READ)
for match in re.finditer('>([^\n]+)([^>]*)', mm, flags=re.DOTALL):
print match.group(1), match.group(2).replace('\n', '')
#GeneID1 ACTCTCTCTATATATATATATGCTCTGCTTCTAGAGAGAGTGTCTATTTGTTTATATATCTTT
#GeneID2 GCTCTGCTTCTAGAAATTCCCACTCTGTATATATTTTCAAAAGCTCTGCTTCTAGAGAGAGTG
这样做可以将整个文件视为字符串,但是将使用提供文件部分的操作系统来完成正则表达式。由于它使用finditer
,我们也没有在内存中构建结果。
答案 3 :(得分:0)
有更简单的方法来读取fasta文件,例如:
entries = []
for line in filer:
if line.startswith('>'):
entries.append((line.rstrip()[1:], []))
else:
entries[-1][1].append(line.rstrip())
这将为您提供元组列表。第一个元素是序列ID,第二个元素是序列列表。
在此之后加入序列很容易:
entries = [(x, "".join(y)) for x,y in entries]