2

我有大约 10 个包含 python 字典的大文件,如下所示:

    dict1:
    {   
        'PRO-HIS-MET': {
            'A': ([1,2,3],[4,5,6],[7,8,9]),
            'B': ([5,2],[6],[8,9]),
            'C': ([3],[4],[7,8])},
        'TRP-MET-GLN': {
            'F': ([-5,-4,1123],[-7,-11,2],[-636,-405])}
    }

    dict2:
    {   
        'PRO-HIS-MET': {
            'J': ([-657], [7,-20,3], [-8,-85,15])}

        'TRP-MET-GLN':{
            'K': ([1,2,3],[4,50,6],[7,80,9]), 
            'L': ([5,20],[60,80],[8,9])}
    }

基本上它们都是字典的字典。每个文件大小约为 1 GB(以上只是数据示例)。无论如何,我想做的就是将这 10 部字典加入到一起:

    final:
    {
        'PRO-HIS-MET': {
            'A': ([1,2,3],[4,5,6],[7,8,9]),
            'B': ([5,2],[6],[8,9]),
            'C': ([3],[4],[7,8])
            'J': ([-657], [7,-20,3], [-8,-85,15])},
        'TRP-MET-GLN': {
            'F': ([-5,-4,1123],[-7,-11,2],[-636,-405])
            'K': ([1,2,3],[4,50,6],[7,80,9]), 
            'L': ([5,20],[60,80],[8,9])}
    }

我在小文件上尝试了以下代码,它工作正常:

    import csv
    import collections
    d1 = {}
    d2 = {}
    final = collections.defaultdict(dict)

    for key, val in csv.reader(open('filehere.txt')):
        d1[key] = eval(val)
    for key, val in csv.reader(open('filehere2.txt')):
        d2[key] = eval(val)

    for key in d1:
        final[key].update(d1[key])
    for key in d2:
        final[key].update(d2[key])

    out = csv.writer(open('out.txt', 'w'))
    for k, v in final.items():
        out.writerow([k, v])

但是,如果我在我的 1 GB 文件上尝试这样做,我会通过将 d1 和 d2 以及最终字典保存在内存中来快速耗尽内存。

我有几个想法:

  1. 有没有一种方法可以让我从分段字典中加载键,比较它们,如果在多个字典中找到相同的键,只需组合值?
  2. 与其将字典合并到一个巨大的文件中(这将来可能会让我记忆犹新),如何在合并数据后创建多个包含一个键的所有值的单独文件?例如,对于上述数据,我将只有:

    pro-his-met.txt:
    'PRO-HIS-MET': {
        'A': ([1,2,3],[4,5,6],[7,8,9]),
        'B': ([5,2],[6],[8,9]),
        'C': ([3],[4],[7,8])
        'J': ([-657], [7,-20,3], [-8,-85,15])}
    trp-met-gln.txt:
    'TRP-MET-GLN': {
        'F': ([-5,-4,1123],[-7,-11,2],[-636,-405])
        'K': ([1,2,3],[4,50,6],[7,80,9]), 
        'L': ([5,20],[60,80],[8,9])}
    

作为生物学家,我没有太多的编程经验(您可能已经猜到上述数据代表了生物信息学问题),因此非常感谢任何帮助!

4

3 回答 3

1

就个人而言,这听起来像是一个问题数据库的原型被发明来解决。是的,您可以通过保留文件自己解决这个问题,并将它们映射到内存中并让操作系统处理交换等,但这确实很复杂,而且很难做得很好。

如果您可以让一个已经投入了数百万工时的数据库来处理它,为什么还要付出所有这些努力呢?这将更有效率,并且作为额外的好处,更容易查询信息。

我已经看到 Oracle DB 存储了超过 10 GB 的数据而没有任何问题,我相信 postgre 也会处理这个问题。好消息是,如果你使用 ORM,你可以抽象出这些细节并担心如果有必要,稍后再谈。

此外,虽然生物信息学不是我的专长,但我很确定周围有针对生物信息学量身定制的特定解决方案——也许其中一个是最合适的?

于 2013-02-20T02:28:09.173 回答
1

shelve模块是一个非常易于使用的 Python 数据库。它远没有真正的数据库强大(为此,请参阅@Voo 的答案),但它可以解决操作大型字典的窍门。

首先,从您的词典创建书架:

import shelve
s = shelve.open('filehere.db', flag='n', protocol=-1, writeback=False)
for key, val in csv.reader(open('filehere.txt')):
    s[key] = eval(val)
s.close()

现在你已经把所有东西都整齐地搁置了,你可以高效地操作字典:

import shelve
import itertools
s = shelve.open('final.db', flag='c', protocol=-1, writeback=False)
s1 = shelve.open('file1.db', flag='r')
s2 = shelve.open('file2.db', flag='r')
for key, val in itertools.chain(s1.iteritems(), s2.iteritems()):
    d = s.get(key, {})
    d.update(val)
    s[key] = d # force write
s.close()
于 2013-02-20T02:55:44.653 回答
0

这个概念应该有效。

我会考虑在每次执行部分键时对文件进行多次传递。并保存该结果。

例如。如果您在一次传递中创建所有键的唯一第一个字符的列表,然后将每个传递处理到新的输出文件。如果它是简单的字母数据,则逻辑选择将是字母表中每个字母的循环。

例如。在“p”通行证中,您将处理“PRO-HIS-MET”

然后,您将在最后结合所有文件的所有结果。

如果您是开发人员,那么如果您可以处理这种交互,上一个答案中的数据库想法可能是最好的方法。这个想法需要创建一个 2 级结构,您可以在其中插入和更新记录,然后使用 SQL 语句查询结果。

于 2013-02-20T02:31:09.527 回答