2

次のようなPython辞書を含む約10個の巨大なファイルがあります。

    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. 辞書を 1 つの巨大なファイルにマージする代わりに (これはおそらく将来メモリの頭痛の種になるでしょう)、データをマージした後に 1 つのキーのすべての値を含む多くの個別のファイルを作成するにはどうすればよいでしょうか? たとえば、上記のデータの場合、次のようになります。

    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

個人的には、データベースが解決するために発明された問題の原型のように思えます。はい、ファイルを保持し、パフォーマンスの最適化のためにそれらをメモリにマップし、OSにスワッピングなどを処理させることでこれを自分で解決できますが、これは本当に複雑で、本当にうまくいくのは難しいです.

数百万の工数が投入された DB に処理を任せられるのであれば、なぜここまでの労力を費やす必要があるのでしょうか。これはより効率的であり、追加の利点として、情報のクエリがはるかに簡単になります。

Oracle DB が 10 GB をはるかに超えるデータを問題なく保存しているのを見たことがあります。postgre もこれを同様に処理すると確信しています。良い点は、ORM を使用すると、これらの核心的な詳細を抽象化して心配することができることです。必要に応じて後でそれらについて説明します。

また、バイオインフォマティクスは私の専門ではありませんが、バイオインフォマティクスに合わせた特定のソリューションがあると確信しています。

于 2013-02-20T02:28:09.173 に答える
1

The shelve module is a very easy-to-use database for Python. It's nowhere near as powerful as a real database (for that, see @Voo's answer), but it will do the trick for manipulating large dictionaries.

First, create shelves from your dictionaries:

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()

Now that you've shelved everything neatly, you can operate on the dictionaries efficiently:

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

このコンセプトは機能するはずです。

キーの一部を実行するたびに、ファイルに対して複数のパスを実行することを検討します。その結果を保存します。

例えば。1 つのパスですべてのキーの一意の最初の文字のリストを作成し、それらの各パスを新しい出力ファイルに処理する場合。単純なアルファベットのデータである場合、論理的な選択はアルファベットの各文字のループになります。

例えば。「p」パスでは、「PRO-HIS-MET」を処理します

次に、最後にすべてのファイルからのすべての結果を結合します。

あなたが開発者で、その種のやり取りを処理できるのであれば、前の回答のデータベースのアイデアがおそらく最良のアプローチです。そのアイデアには、レコードを挿入して更新し、SQL ステートメントで結果をクエリする 2 レベルの構造を作成する必要があります。

于 2013-02-20T02:31:09.527 に答える