繁体   English   中英

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

[英]Fastest way to read large file(>8GB) and dump data into dictionary and load it again

我正在处理一个大的蛋白质序列(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 

数据库是我儿子的朋友。

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)

对于通用数据结构, cPickle是迄今为止最快的。

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

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

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

如果您遇到字典,则相当于shelve模块。

好吧,你的问题实际上是如何处理大量数据,而不一定是python。 事情是,无论你尝试什么,你只是不想在你的内存中加载> 8GB,因为它将使你的应用程序交换,每次你试图访问一个元素,你将有页面/页面 - 从RAM出来。

我这样做的方法是将数据集实际排序在多个文件中,这些文件可以很容易地被腌制,每个文件使用键上的一些哈希函数进行排序,这样就可以快速加载分割数据集。 然后,您只加载与散列函数条件匹配的数据集,这将快速完成,并提取密钥的值。

最后,总是使用cPickle ,它是Pickle的C实现,对于加载和转储应该更快(尽管我从未亲自制作过基准测试)。

注意:那个解决方案在某种程度上是穷人的数据库。 当然,@ freakish的建议和@ Jakob使用数据库的解决方案是一个非常好的主意。 虽然我建议的解决方案是在网络节点上分发数据集的常用方法,但是要在多个服务器之间分配存储。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM