2011-09-12 31 views
0

私はxmlファイルから大量のデータを取得していますが、すべてのデータを互いに照合する必要があります(50万レコードを超えている)。それは位置データなので、郡、路線接頭辞、路線接尾辞、通り名、出発家屋番号、終了番号などの情報があります。重複やハウスナンバーオーバーラップなどがあり、問題のある場所など、すべてのデータを報告する必要があります。また、xmlファイル内にデータの順序はありません。したがって、各レコードは他のすべてのレコードと照合する必要があります。Pythonでデータをサニタイズするための大きなテンポラリデータベース

今、私は通りの名前情報に基づいて場所の辞書を作成し、その家の番号の開始と終了の場所のリストを保存しています。この作業がすべて完了したら、各リスト内で重複や重複を見つけるために作成された膨大なデータ構造を繰り返しています。私はデータ構造のサイズやエラーの数に問題があります。

私に示唆された解決策の1つは、ファイルから読み込まれたすべてのデータを保持するために一時的なSQLite DBを作成し、DBを実行してデータに関するすべての問題を見つけ出し、報告してから破棄することでしたDB。これを行うためのより良い/より効率的な方法がありますか?そして、この問題に近づくためのよりよい方法に関する提案はありますか?

fyiとして、私が読み込んでいるxmlファイルは500MBを超えています(これは大部分ですが、この通りの情報以外のデータも保存しています)が、ファイルの処理は私の所ではありません問題が発生すると、ファイルから取得したデータを処理するときのみです。

EDIT:私は詳細に行くことができましたが、データのためにメモリに十分な空きがあると述べたポスターは実際には正しかったですが、1つのケースではこれを350万レコードに対して実行しなければなりませんでした。インスタンス私は一時的なデータベースを作成する必要がありました。

+0

Python標準ライブラリbsddbパッケージの使用を検討してください。ディクショナリインターフェイスを提供しますが、ディスク上のハッシュテーブルまたはbツリーのいずれかによってサポートされています。 –

+0

これは2.6以降で廃止予定ですhttp://docs.python.org/library/bsddb.html –

+0

OK、http://www.jcea.es/programacion/pybsddb.htmとbsddb3モジュールを使用してください...同じ考え方、わずかに異なる名前。 –

答えて

0

500,000は大した数字ではありません。なぜなら、すべてのレコードで、関連するエントリからdictを作成し、確認する必要があるものをチェックしてください。

import random 
import time 

class Data(object): 
    ID = 0 
    def __init__(self, data): 
     Data.ID+=1 
     self.id =Data.ID 
     self.data = data 
     self.duplicates = None 

def fill_data(N): 
    data_list = [] 
    # create alist of random data 
    sample = list("anuraguniyal") 
    for i in range(N): 
     random.shuffle(sample) 
     data_list.append(Data("".join(sample))) 
    return data_list 

def find_duplicate(data_list): 
    data_map = {} 
    for data in data_list: 
     if data.data in data_map: 
      data_map[data.data].append(data) 
     else: 
      data_map[data.data] = [data] 

     data.duplicates = data_map[data.data] 

st = time.time() 
data_list = fill_data(500000) 
print "fill_data time:", time.time()-st 
st = time.time() 
find_duplicate(data_list) 
print "find_duplicate time:", time.time()-st 

total_duplicates = 0 
max_duplicates = 0 
for data in data_list: 
    total_duplicates += (len(data.duplicates) - 1) 
    max_duplicates = max(len(data.duplicates),max_duplicates) 
print "total_duplicates count:",total_duplicates 
print "max_duplicates count:",max_duplicates 

出力:

fill_data time: 7.83853507042 
find_duplicate time: 2.55058097839 
total_duplicates count: 12348 
max_duplicates count: 3 

したがって、この場合のシナリオは、それは同様の方法でどのように異なるを行うことができますか?

+0

それはおそらくそれよりも難しいでしょう。私は彼が '重複している可能性が高い'ものを排除したいと思うし、正確にマッチするハッシュ・ルックアップを行うことはできないと思うだろう。 –

+0

@rrenaud、そうかもしれないが、1)どのようなDBなどを使ってもそれを単純化したり速度を上げたりしないだろう2)データを前処理して標準化すると重複した問題が解決される可能性がある –

0

PAF(英国の郵便局のアドレスファイル - 基本的には英国のすべての住所)に対してこのデータが既に浄化されていない限り、同じ実際の家であるが異なる綴りの住所、間違った郵便番号、郵便番号これはあなたのアプローチを完全に変えるでしょう。

開始する前にこれが消毒されているかどうかを確認してください。あなたにそれを渡す人は、「はい、もちろんありますし、私もやった」と言うか、まったく見えません。

浄化されている場合はおそらく外部の代理店があなたのデータを提供していると思いますが、これはおそらくあなたのために行うことができます。乗る。

ない場合、あなたはなど、彼らが試合のようにしたいどのようconfidnet、問題の範囲を持っているし、彼らが望むものについてのあなたの上司と話をする必要があります

一般的な考え方は、数を思い付くことです比較の対象となる2つのアドレスが同じである確信度値を出力します。次に、これらの値のいくつかが重み付けされ、2つのアドレスが一致するとみなすために合計confidnece値を渡さなければなりません。

しかしこれはあなたの問題ですが、私はあなたの上司これはマーケティングとテクニカルデパットの間に明確に理解されている領域ではありません。

+0

OPは国郵便システムが「PAF」を提供する場合、合理的な第一歩は最低の住宅番号を使用して各レコードを浄化することであろう。それはどちらかかなりOK、通りなどのコンポーネントの変更でOK、認識できない/固定できない、通りなどOKですが数字は悪いです。その後、結果に応じて最高のハウスナンバーで繰り返すこともできます。恐ろしい考え:おそらく、いくつかの小さな領域にPAFを組み立てることです。別の問題は、公益事業や緊急サービスの場合、「配達」住所は必ずしも郵便住所ではないということです。 –

関連する問題