2011-08-14 22 views
1

与えられる: 2つのcsvファイル(それぞれ1.8 MB):AllData_1、AllData_2。それぞれ〜8,000行あります。各行は8列で構成されています。 [txt_0、txt_1、txt_2、txt_3、txt_4、txt_5、txt_6、txt_7、txt_8]Python 2の比較最適化リスト

目標: txt_0の一致(または、AllData_1 [0] == AllData_2)に基づいて、内容を比較しますこれらの個々の行の次の4つの列。データが不一致の場合は、異なる列に基づいてリスト内の各データセットの行全体を入れ、リストを出力ファイルに保存します。 txt_0が1つのデータセットで他のデータセットでない場合は、出力ファイルに直接保存します。

例:

AllData_1列xが含まれています:[A1、B2、C3、D4、E5、F6、G7、H8]は AllData_2行yが含まれている:[A1、B2、c33cの、d44d、E5、F6を、g7、h8]

プログラムは、行xとyのすべてをListCol2とListCol3に対応するリストに保存します。すべての比較が終了すると、リストがファイルに保存されます。

コードを高速化したり、コードをより高速なアルゴリズムに変更するにはどうすればよいですか?

i = 0 
x0list = [] 
y0list = [] 
col1_diff = col2_diff = col3a_diff = col3b_diff = col4_diff = [] 

#create list out of column 0 
for y in AllData_2: 
    y0list.append(y[0]) 

for entry in AllData_1: 
    x0list.append(entry[0]) 
    if entry[0] not in y0list: 
     #code to save the line to file... 

for y0 in AllData_2: 
    if y0[0] not in x0list: 
     #code to save the line to file... 

for yrow in AllData_2: 
    i+=1 

    for xrow in AllData_1: 
     foundit = 0 
     if yrow[0] == xrow[0] and foundit == 0 and (yrow[1] != xrow[1] or yrow[2] != xrow[2] or yrow[3] != xrow[3] or yrow[4] != xrow[4]): 
      if yrow[1] != xrow[1]: 
       col1_diff.append(yrow) 
       col1_diff.append(xrow) 
       foundit = 1 

      elif yrow[2] != xrow[2]: 
       col2_diff.append(yrow) 
       col2_diff.append(xrow) 
       foundit = 1 

      elif len(yrow[3]) < len(xrow[3]): 
       col3a_diff.append(yrow) 
       col3a_diff.append(xrow) 
       foundit = 1 

      elif len(yrow[3]) >= len(xrow[3]): 
       col3b_diff.append(yrow) 
       col3b_diff.append(xrow) 
       foundit = 1 

      else: 
       #col4 is actually a catch-all for any other differences between lines if [0]s are equal 
       col4_diff.append(yrow) 
       col4_diff.append(xrow) 
       foundit = 1 
+0

多分これはhttp://stackoverflow.com/questions/744256/reading-huge-file-in-pythonを助けることができる –

+1

使用すると、メンバーシップ・テストのためにリストを設定していません。 – katrielalex

+0

'foundit == 0'とは何でしょうか? 'foundit'がテストの直前に0に設定されているので、常に真です。 –

答えて

1

あなたは、列0で同じデータを持つように指定したファイルには2つの行を期待することはできません場合は、かなり少数dict sのあなたのコードを向上させることができます。代わりにライン

x0list.append(entry[0]) 
y0list.append(y[0]) 

のあなたは使用します。

x0dict[entry[0]] = entry 
y0dict[y[0]] = y 

{}x0dicty0dictを初期化した後。その後、代わりにdictsのひとつ以上のことができますループ再びデータの両方の完全なセットをループで:

for x0, xrow in x0dict: 
    if x0 in y0dict: 
     yrow = y0dict[x0] 
     # Do the col{1,2,3,4}_diff stuff here 
ボーナスとして

、あなたの第二と第三のループでnot in同じように動作します。


ラインは

(yrow[1] != xrow[1] or yrow[2] != xrow[2] or yrow[3] != xrow[3] or yrow[4] != xrow[4]) 

あなたのコードは今の現状ではiが使用されることはありません、すてきに見える

yrow[1:5] != xrow[1:5] 

に置き換えられていますが、必要な場合はすることができますそのカウントは、それは単にi = len(AllData_2)と同じになります。なぜなら、それは1回の実行で1回だけ増分するからですAllData_2をループします。


最後に、foundit変数は、現在は用途がありません。 foundit == 0でフローを制御するときには、0に設定した直後にのみ使用されるため、常にTrueと評価され、設定は無効です。

+0

'yrow [1:5]'と 'xrow [1:5]'を直接比較できないのはなぜですか?スライスはシーケンスであり、要素ごとに比較されます。 –

+0

@KarlOops、現在のプロジェクトはcoffeescriptであり、正しく動作しないことに慣れています。編集されました。 –

+0

お返事ありがとうございました。私はいくつかのフォローアップの質問があります。比較の大部分については、最初の列が一致する行を探しています。しかし、私は不必要なi(あまりにも多くの速度利得ではない)とfoundit比較(〜25%の速度利得)の世話をした。再度、感謝します! – Mark

1

右上の方が、これをもっと小さくすることができます。

y0list = [] 
for y in AllData_2: 
    y0list.append(y[0]) 

y0list = [y[0] for y in AllData_2] 

を言うだけの冗長な方法であり、あなたは、組み込みの比較で使用することができます。

(yrow[1] != xrow[1] or yrow[2] != xrow[2] or yrow[3] != xrow[3] or yrow[4] != xrow[4]) 

以下 ザは、はるかに少ない傾向/ペーストエラーをコピーすることである

yrow[1:] != xrow[1:] 

として表すことができます。

もっと速くするために、O(n ** 2)の比較を避けることができます。最初の列要素が同じときだけ気にするので、最初の要素で束縛することができます。

index = {} 
for yrow in AllData_2: 
    key = yrow[0] 
    list = index.get(key) 
    if list is None: 
     list = [] 
     index[key] = list 
    list.append(yrow) 

for xrow in AllData_1: 
    list = index.get(xrow[0]) 
    if list is None: continue 
    for yrow in list: 
     # Do all your comparison here 
+0

おかげさまで、特にO(n ** 2)コードをお寄せいただきありがとうございます。バンドルは、2つの最初の比較が今では欠けていることを除いて、素晴らしい仕事をします。 all_yとy [0]にないx [0]は、all_x(上記の元のコードとは異なるコード)に追加できません。 – Mark

関連する問題