很难解决这个问题或者找到关于它的任何好的提示。
我试图循环一个文件,稍微修改每一行,然后循环不同的文件。如果第二个文件中的行以第一个文件中的行开头,那么第二个文件中的跟随行应该写入第三个文件。
with open('ids.txt', 'rU') as f:
with open('seqres.txt', 'rU') as g:
for id in f:
id=id.lower()[0:4]+'_'+id[4]
with open(id + '.fasta', 'w') as h:
for line in g:
if line.startswith('>'+ id):
h.write(g.next())
显示所有正确的文件,但它们是空的。是的,我确定如果有真实案例。 :-)
“seqres.txt”包含具有特定格式的ID号的行,每行后跟一行数据。 “ids.txt”具有不同格式的感兴趣的ID号。我希望每行数据在其自己的文件中都有一个有趣的ID号。
万分感谢任何有一点建议的人!
这是最小的解决方案,但请看下面的答案:
with open('ids.txt', 'rU') as f:
fl = f.readlines()
with open('seqres.txt', 'rU') as g:
gl = g.readlines()
for id in fl:
id=id.lower()[0:4]+'_'+id[4]
with open(id + '.fasta', 'w') as h:
for line in xrange(len(gl)):
if gl[line].startswith('>'+ id):
h.write(gl[line+1])
答案 0 :(得分:2)
这是一个大致扁平化的实现。根据您为每个ID获得的点击数量,以及“seqres”中有多少条目,您可以重新设计它。
# Extract the IDs in the desired format and cache them
ids = [ x.lower()[0:4]+'_'+x[4] for x in open('ids.txt','rU')]
ids = set(ids)
# Create iterator for seqres.txt file and pull the first value
iseqres = iter(open('seqres.txt','rU'))
lineA = iseqres.next()
# iterate through the rest of seqres, staggering
for lineB in iseqres:
lineID = lineA[1:7]
if lineID in ids:
with open("%s.fasta" % lineID, 'a') as h:
h.write(lineB)
lineA = lineB
答案 1 :(得分:1)
问题是你只是循环遍历文件g一次 - 在你第一次将文件索引位置留在文件末尾时读完它之后,所以任何进一步的读取都会因EOF而失败。每次循环都需要重新打开g。
然而,这将是非常低效的 - 您正在重复读取相同的文件,f中的每一行一次。在开始时将所有g读入数组并使用它会快几个数量级,只要它适合内存。
答案 2 :(得分:1)
对于速度,你真的想避免多次循环同一个文件。这意味着当你使用O(N + M)算法时,你已经变成了O(N * M)算法。
要实现此目的,请将id列表读入快速查找结构(如集合)。由于只有4600这种内存形式不应该有任何问题。
新解决方案还将列表读入内存。可能不是一个只有几十万行的巨大问题,但它浪费的内存比你需要的多,因为你可以在一次通过中完成整个过程,只将较小的ids.txt文件读入内存。你可以在上一行有趣的时候设置一个标志,这将指示下一行写出来。
这是一个重新设计的版本:
with open('ids.txt', 'rU') as f:
interesting_ids = set('>' + line.lower()[0:4] + "_" + line[4] for line in f) # Get all ids in a set.
found_id = None
with open('seqres.txt', 'rU') as g:
for line in g:
if found_id is not None:
with open(found_id+'.fasta','w') as h:
h.write(line)
id = line[:7]
if id in interesting_ids: found_id = id
else: found_id = None
答案 3 :(得分:1)
我认为从你宣布为最终的代码仍然有进步。你可以使结果少一些嵌套,避免一些愚蠢的事情。
from contextlib import nested
from itertools import tee, izip
# Stole pairwise recipe from the itertools documentation
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return izip(a, b)
with nested(open('ids.txt', 'rU'), open('seqres.txt', 'rU')) as (f, g):
for id in f:
id = id.lower()[0:4] + '_' + id[4]
with open(id + '.fasta', 'w') as h:
g.seek(0) # start at the beginning of g each time
for line, next_line in pairwise(g):
if line.startswith('>' + id):
h.write(next_line)
这是对您在
中发布的最终代码的改进g
的最佳选择,真的。它肯定会更好地扩展。)gl[line+1]
的最后一行,它不包含使用gl
的崩溃条件
g
的实际情况,可能会有比pairwise
更适用的内容。f
的长度无限制,您可以使用一组ID来将算法减少到O(n)(g
中的行数线性)。答案 4 :(得分:0)
处理完ids.txt
文件中的第一行后,文件seqres.txt
已用尽。嵌套嵌套有问题。此外,您正在修改for line in g
循环内的迭代器。不是个好主意。
如果你真的想追加ID匹配的行后面的行,那么这样的事情可能会更好:
with open('ids.txt', 'rU') as f:
ids = f.readlines()
with open('seqres.txt', 'rU') as g:
seqres = g.readlines()
for id in ids:
id=id.lower()[0:4]+'_'+id[4]
with open(id + '.fasta', 'a') as h:
for line in seqres:
if line.startswith('>'+ id):
h.write(seqres.next())