我有两个大文件。其中一个是信息文件(大约270MB和16,000,000行),如下所示:
1101:10003:17729
1101:10003:19979
1101:10003:23319
1101:10003:24972
1101:10003:2539
1101:10003:28242
1101:10003:28804
另一种是标准的FASTQ格式(约27G和280,000,000行),如下所示:
@ST-E00126:65:H3VJ2CCXX:7:1101:1416:1801 1:N:0:5
NTGCCTGACCGTACCGAGGCTAACCCTAATGAGCTTAATCAAGATGATGCTCGTTATGG
+
AAAFFKKKKKKKKKFKKKKKKKFKKKKAFKKKKKAF7AAFFKFAAFFFKKF7FF<FKK
@ST-E00126:65:H3VJ2CCXX:7:1101:10003:75641:N:0:5
TAAGATAGATAGCCGAGGCTAACCCTAATGAGCTTAATCAAGATGATGCTCGTTATGG
+
AAAFFKKKKKKKKKFKKKKKKKFKKKKAFKKKKKAF7AAFFKFAAFFFKKF7FF<FKK
FASTQ文件每个序列使用四行。第1行以“@”字符开头,后跟序列标识。对于每个序列,第1行的这一部分是唯一的。
1101:1416:1801 and 1101:10003:75641
我想根据信息文件从FASTQ文件中获取第1行和后3行。这是我的代码:
import gzip
import re
count = 0
with open('info_path') as info, open('grab_path','w') as grab:
for i in info:
sample = i.strip()
with gzip.open('fq_path') as fq:
for j in fq:
count += 1
if count%4 == 1:
line = j.strip()
m = re.search(sample,j)
if m != None:
grab.writelines(line+'\n'+fq.next()+fq.next()+fq.next())
count = 0
break
并且它有效,但由于这两个文件都有数百万行,因此效率低(运行一天只能获得20,000行)。
7月6日更新:
我发现信息文件可以读入内存(感谢@tobias_k提醒我),所以我创建了一个字典,键是信息行,值都是0.之后,我读了FASTQ文件每4行,使用标识符部分作为键,如果值为0则返回4行。这是我的代码:
import gzip
dic = {}
with open('info_path') as info:
for i in info:
sample = i.strip()
dic[sample] = 0
with gzip.open('fq_path') as fq, open('grap_path',"w") as grab:
for j in fq:
if j[:10] == '@ST-E00126':
line = j.split(':')
match = line[4] +':'+line[5]+':'+line[6][:-2]
if dic.get(match) == 0:
grab.writelines(j+fq.next()+fq.next()+fq.next())
这种方式要快得多,需要20分钟才能获得所有匹配的行(约64,000,000行)。我已经考虑过首先通过外部排序对FASTQ文件进行排序。拆分可以读入内存的文件是可以的,我的麻烦是如何在排序时将下三行保留在标识符行之后。谷歌的答案是首先将这四行线性化,但这需要40分钟。
无论如何,谢谢你的帮助。
答案 0 :(得分:2)
您可以按标识符(1101:1416:1801
)部分对这两个文件进行排序。即使文件不适合内存,也可以使用external sorting。
在此之后,您可以应用简单的类似合并的策略:同时读取两个文件并在此期间进行匹配。像这样的东西(伪代码):
entry1 = readFromFile1()
entry2 = readFromFile2()
while (none of the files ended)
if (entry1.id == entry2.id)
record match
else if (entry1.id < entry2.id)
entry1 = readFromFile1()
else
entry2 = readFromFile2()
这种方式entry1.id
和entry2.id
总是彼此靠近,你不会错过任何比赛。同时,这种方法需要迭代每个文件一次。