通过相同的键加入大词典

时间:2013-02-20 02:19:36

标签: python bioinformatics dictionary defaultdict

我有大约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])}
    
  3. 作为一名生物学家,我没有太多的编程经验(您可能已经猜到上述数据代表了生物信息学问题),所以任何帮助都会非常感激!

3 个答案:

答案 0 :(得分:1)

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

为什么要经历所有这些努力,如果你能让一个数据库 - 数百万工时被放入 - 处理它?这将更有效,并且作为额外的好处更容易查询信息。

我已经看到Oracle数据库存储了超过10 GB的数据而没有任何问题,我确信postgre也会处理这个...好的是如果你使用ORM你可以抽象那些细节的细节如果有必要,请稍后离开并担心。

虽然生物信息学不是我的专长,但我非常确定有针对生物信息学的特定解决方案 - 也许其中一个是最合适的?

答案 1 :(得分: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()

答案 2 :(得分:0)

这个概念应该有用。

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

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

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

然后你将结合所有文件的所有结果。

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