读取大文件(>8GB)并将数据转储到字典并再次加载的最快方法

2024-10-04 15:28:30 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在处理一个大型蛋白质序列(fasta)文件(>;8GB),我的想法是创建字典,其中键和值分别是蛋白质id和序列。

现在我可以使用pickle创建数据并将其转储到字典中,然后尝试使用cpickle打开(我读取pickle转储数据更快,而cpickle加载数据更快)。但这里的主要问题是时间:把它作为字典来制作和转储需要花费太多的时间和内存(PC有8GB的内存)。

在Python中有没有更快的方法来处理大文件?

下面是创建字典和转储数据的Python代码:

from Bio import SeqIO
import pickle,sys

fastaSeq = {}
with open('uniref90.fasta') as fasta_file:
    for seq_record in SeqIO.parse(fasta_file, 'fasta'):
       header =seq_record.id
       uniID = header.split('_')[1]
       seqs = str(seq_record.seq)
       fastaSeq[uniID] = seqs

f = open('uniref90.obj', 'wb')
pickle.dump(fastaSeq, f, pickle.HIGHEST_PROTOCOL)
f.close()

加载字典并在单独的Python程序中执行某些任务:

import cPickle as pickle
seq_dict = pickle.load(open("uniref90.obj", "rb"))
for skey in seq_dict.keys():
   #doing something 

Tags: 文件数据importid字典序列蛋白质open
3条回答

对于一般数据结构来说,cPickle是最快的。

根据数据结构施加的约束,请尝试ujson,这是一种更快的JSON实现,请注意,可能需要传递一些标志以保持浮点值的准确性。

如果您的数据是平面的,那么numpy.load变量将更快。有格式选项,从文本到二进制数据。

最后numpy.mmap允许您访问二进制数据,而不必“加载”它本身,也就是说,数据只有在您访问它时才会到达RAM。那应该是目前为止最快的。

如果您被字典缠住了,那么等效的是shelve模块。

好吧,问题在于如何处理大量数据,而不一定是使用python。问题是,无论您尝试什么,您都不想在内存中加载>;8GB,因为它将使您的应用程序进行交换,并且每次您尝试访问元素时,都会从RAM中进行页输入/页输出。

我要做的方法是在多个文件中对数据集进行排序,这些文件可以很容易地进行pickle,每个文件都使用键上的哈希函数进行排序,这样就可以快速加载拆分的数据集。然后只加载与hash函数条件匹配的数据集(将快速完成),并提取密钥的值。

最后,始终使用cPickle,这是Pickle的一个C实现,对于加载和转储应该更快(尽管我从未亲自做过基准测试)。

注意:这个解决方案不知怎的是poorman的数据库。当然,@freakish的建议和@Jakob使用数据库的解决方案确实是个好主意。尽管我建议的解决方案是在网络节点上分发数据集,在多个服务器上分发存储。

数据库是你的朋友我的儿子。

import sqlite3
from Bio import SeqIO

db = sqlite3.connect("./db")

c = db.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS map (k text unique, v text)''')
db.commit()


def keys(db):
    cursor = db.cursor()
    return cursor.execute("""SELECT k FROM map""").fetchall()


def get(key, db, default=None):
    cursor = db.cursor()
    result = cursor.execute("""SELECT v FROM map WHERE k = ?""", (key,)).fetchone()
    if result is None:
        return default
    return result[0]


def save(key, value, db):
    cursor = db.cursor()
    cursor.execute("""INSERT INTO map VALUES (?,?)""", (key, value))
    db.commit()


with open('uniref90.fasta') as fasta_file:
    for seq_record in SeqIO.parse(fasta_file, 'fasta'):
       header = seq_record.id
       uniID = header.split('_')[1]
       seqs = str(seq_record.seq)
       save(uniID, seqs, db)

相关问题 更多 >

    热门问题