【问题标题】:Process Massive Files (> 60GB each) To Replace Lines From One File to Another And Write To New File Python处理大量文件(每个 > 60GB)以将行从一个文件替换到另一个文件并写入新文件 Python
【发布时间】: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 文件,因此性能仍然可以接受。恕我直言,它可能值得一试......

标签: python bigdata


【解决方案1】:

总体而言,如果您想处理大量工作负载,则需要以某种方式将其拆分。使用文件,这有点容易:您只需要分块读取它。

在本例中,函数读取变量batch 指定的行数,然后针对整个文件运行该数据并写入创建的结果,然后循环返回并获取下一行行,直到没有更多行。

def big_merge_out(in_a, in_b, out, batch=2):
    # Old style of file handling
    file_a = open(in_a, 'r')
    file_b = open(in_b, 'r')
    result = open(out, 'w')

    def next_batch(content):
        content.clear()
        for _ in range(batch):
            a_line_k = file_a.readline()
            a_line_v = file_a.readline()

            if not a_line_k or not a_line_v:
                break
            if a_line_k[0] != '@':
                continue

            # (1) Your read data thing
            key = a_line_k.split()[0]
            content[key] = a_line_v[:20]

        if content:
            return True
        else:
            return False

    data = {}
    while next_batch(data):
        file_b.seek(0, 0)
        while True:
            b_line = file_b.readline()
            if not b_line:
                break
            if b_line[0] != '@':
                continue

            # (2) Your write data thing
            key = b_line.split()[0]
            if key in data:
                key = key + '_' + data[key]
            sequence = next(file_b)
            blank = next(file_b)
            quality = next(file_b)

            result.write(key + '\n')
            result.write(sequence + blank + quality)

    file_a.close()
    file_b.close()
    result.close()


if __name__ == '__main__':
    big_merge_out('A.txt', 'B.txt', 'D.txt')

(因为我无法弄清楚代码应该如何处理您提供的示例,您必须修复或替换 # (1)# (2)。)

【讨论】:

    猜你喜欢
    • 2020-09-21
    • 2018-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多