【发布时间】:2021-07-07 15:26:01
【问题描述】:
我有两个文件(均为 60GB),预计将来会有更大的文件,目标是通过将某些行合并在一起来操作第一个文件,然后进入一个新文件并查看第二个文件中的行是否匹配从第一个文件中提取的合并行中提取部分行,然后将结果写入新文件。
起初,我从第一个文件创建了一个字典——键是 ID,值是合并的部分。然后,我让程序查看第二个文件,看看这些行是否与键匹配,然后让那行 = 键加上值。最后,我把这一切都写到了一个新文件中。这适用于每个大小为 30GB 的文件,但现在它被杀死了。这是我的脚本:
## create dictionary
readID_dictionary = {}
## open the read 1 fastq file as R1
with open(R1_Path, 'rt') as R1:
for line in R1:
if line[0] != '@': continue
readID = line.split()[0]
readID_dictionary[readID] = next(R1)[:20]
with open(R2_Path, 'rt') as R2:
with open(newfile, "w") as newfile:
for line in R2:
if line[0] != '@': continue
readID = line.split()[0]
if readID in readID_dictionary:
readID = readID + '_' + readID_dictionary[readID]
sequence = next(R2)
blank = next(R2)
quality = next(R2)
newfile.write(readID +'\n')
newfile.write(sequence + blank + quality)
有人有什么想法吗?我在想字典是绝对会减慢它并杀死它的东西。我尝试使用字典中的项目创建一个文件,并认为我可以搜索两个文件之间的匹配行,但没有运气。
这是我将要转换为字典的第一个文件的示例(我认为这会导致内存问题):
@Alex 您可以将其用于我将要转换为字典的第一个文件的示例(就记忆而言,我认为这是主要问题):
@id:number:one_FFKF
@id:number:two_KKKK
@id:number:three_NGTG
@id:number:four_IOPL
@id:number:five_YIOK
@id:number:six_OPOP
对于第二个文件,我将获取以“@”开头的每一行,看看它是否与字典中的行匹配(或者第一个文件的结果在哪里——甚至直接来自第一个文件)最好),如果匹配,则将其替换为第一个文件中的行,并保留第二个文件中的其余部分。最后,将新结果写入新文件。
@id:number:one
ASKLJDFSJKLF
+
LLLLLLLLLL
@id:number:two
LKSDJF:LSDKFJ
+
LLLJKJKLLLLL
@id:number:eight_NGTG
LSDKJ:FLKSDFJ
@id:number:twenty_IOPL
+
LKJLLLLLKJKLJL
@id:number:eleven_YIOK
LKSJDF:LKSDJF
+
LLKJLKLLLLLLL
@id:number:ten_OPOP
KSJDHFLSKDJFH
+
LKLKLLLLLLLLL
【问题讨论】:
-
您的脚本有大象的内存占用。它很可能被杀死,因为它用尽了所有 RAM。您将不得不想出一个解决方案,它不会在内存中存储太多数据。
-
是字典的使用占用了这么多内存吗?
-
不是你用字典。事实上,你用大量的数据填充它们。
-
那么你会推荐什么?
-
一种缓慢但稳健的方法是将字典替换为
shelve。但由于底层数据结构是 xdbm 文件,因此性能仍然可以接受。恕我直言,它可能值得一试......