1

リストの巨大なpythonリスト(A)があります。リスト A の長さは約 90,000 です。各内部リストには、約 700 のタプルが含まれています(datetime.date,string)。今、このデータを分析しています。私がやっていることは、サイズ x のウィンドウを内部リストx = len(inner list) * (some fraction <= 1)where- に取り、そのウィンドウで a が b の前に発生する順序付けられた各ペア (a、b) を保存していることです (実際、内部リストは時間ごとにソートされます)。このウィンドウを最後の要素まで移動して、一方の端から一度に 1 つの要素を追加し、もう一方の端から削除しO(window-size)ます。新しいタプルのみを検討しているため、時間がかかります。私のコード:

for i in xrange(window_size):
        j = i+1;
        while j<window_size:
            check_and_update(cur, my_list[i][1], my_list[j][1],log);
            j=j+1

    i=1;
    while i<=len(my_list)-window_size: 
        j=i;
        k=i+window_size-1;
        while j<k:
            check_and_update(cur, my_list[j][1], my_list[k][1],log);  
            j+=1
        i += 1  

これは実際にはsqlite3curデータベース カーソルでmy_listあり、タプルを含むリストであり、A のすべてのリストに対してこのコードを反復しlog、開いたログ ファイルです。メソッドcheck_and_update()では、データベースを検索して、存在する場合はタプルを検索するか、それ以外の場合はそれを挿入し、これまでの合計出現回数を示します。コード:

def check_and_update(cur,start,end,log):    
    t = str(start)+":"+ str(end)
    cur.execute("INSERT OR REPLACE INTO Extra (tuple,count)\
                 VALUES ( ? , coalesce((SELECT count +1 from Extra WHERE tuple = ?),1))",[t,t])

予想どおり、この数のタプルは巨大であり、私は以前にメモリを非常に速く消費する辞書で実験しました。それで、私は SQLite3 に頼りましたが、今は遅すぎます。インデックスを作成しようとしましたが、助けがありませんでした。おそらく私のプログラムは、データベースのクエリと更新に多くの時間を費やしています。この問題に対する最適化のアイデアはありますか? おそらく、アルゴリズムまたはいくつかの異なるアプローチ/ツールを変更します。ありがとうございました!

編集:ここでの私の目標は、ウィンドウ内で発生する文字列のタプルの総数を、それらが発生するさまざまなインナーリストの数でグループ化して見つけることです。この情報を次のクエリで抽出します。

for i in range(1,size+1):       
        cur.execute('select * from Extra where count = ?',str(i))
        #other stuff

例(日付エントリを無視して「dt」と書きます):

My_list = [
            [ ( dt,'user1') , (dt, 'user2'), (dt, 'user3') ]
            [ ( dt,'user3') , (dt, 'user4')]
            [ ( dt,'user2') , (dt, 'user3'), (dt,'user1') ]
          ]

ここで分数 = 1 を取ると、結果は次のようになります。

only 1 occurrence in window: 5 (user 1-2,1-3,3-4,2-1,3-1)
only 2 occurrence in window: 2 (user 2-3)
4

2 に答える 2

2

これをはっきりさせてください。

最大約 220 億の潜在的なタプル (90000 のリストの場合、700 のいずれか、次のエントリのいずれか、平均で 350) があり、ウィンドウ サイズによっては少なくなる可能性があります。見つけたいのですが、それらが表示される内部リストの数、タプルの数です。

このサイズのデータ​​はディスク上に存在する必要があります。サイズが原因でディスク上に存在するデータのルールは、「ランダムにアクセスするのではなく、生成してから並べ替える」です。

したがって、各タプルを 1 行に 1 タプルずつ、ログ ファイルに書き出すことをお勧めします。そのファイルを並べ替えます。これで、特定のタプルのすべてのインスタンスが 1 か所にまとめられました。次に、ファイルを実行し、タプルごとに、出現回数のカウントを出力します (つまり、内部リストの数です)。その 2 番目のファイルを並べ替えます。そのファイルを実行すると、1x、2x、3x などのタプルの数を抽出できます。

複数のマシンがある場合、これを MapReduce に変換するのは簡単です。(道徳的には同じアプローチですが、多くのものを並列化できます。)

于 2012-05-30T06:51:45.050 に答える
1

Apache Hadoopは、この種の問題に適した MapReduce 実装の 1 つです。

于 2012-05-30T10:00:28.157 に答える