簡體   English   中英

如何使用嵌套字典使模糊匹配代碼更有效?

[英]How can I use nested dictionaries to make my fuzzy matching code more efficient?

我有2個字典(字典閱讀器)列表,看起來像這樣:

名1

 [{'City' :'San Francisco', 'Name':'Suzan', 'id_number' : '1567', 'Street': 'Pearl'},
     {'City' :'Boston', 'Name':'Fred', 'id_number' : '1568', 'Street': 'Pine'},
     {'City' :'Chicago', 'Name':'Lizzy', 'id_number' : '1569', 'Street': 'Spruce'},
     {'City' :'Denver', 'Name':'Bob', 'id_number' : '1570', 'Street': 'Spruce'}
     {'City' :'Chicago', 'Name':'Bob', 'id_number' : '1571', 'Street': 'Spruce'}
     {'City' :'Boston', 'Name':'Bob', 'id_number' : '1572', 'Street': 'Canyon'}
     {'City' :'Boulder', 'Name':'Diana', 'id_number' : '1573', 'Street': 'Violet'}
     {'City' :'Detroit', 'Name':'Bill', 'id_number' : '1574', 'Street': 'Grape'}]

名稱2

[{'City' :'San Francisco', 'Name':'Szn', 'id_number' : '1567', 'Street': 'Pearl'},
 {'City' :'Boston', 'Name':'Frd', 'id_number' : '1578', 'Street': 'Pine'},
 {'City' :'Chicago', 'Name':'Lizy', 'id_number' : '1579', 'Street': 'Spruce'},
 {'City' :'Denver', 'Name':'Bobby', 'id_number' : '1580', 'Street': 'Spruce'}
 {'City' :'Chicago', 'Name':'Bob', 'id_number' : '1580', 'Street': 'Spruce'}
 {'City' :'Boston', 'Name':'Bob', 'id_number' : '1580', 'Street': 'Walnut'}]

如果您發現第二個塊中的名稱與第一個塊的拼寫有所不同,但其中幾個幾乎相同。 我想使用模糊字符串匹配來進行匹配。 我還想縮小到僅比較同一城市和同一條街道上的名稱的位置。 目前,我正在運行一個看起來像這樣的for循環

from fuzzywuzzy import fuzz
from  fuzzywuzzy import process
from itertools import izip_longest
import csv

name1_file = 'name1_file.csv'
node_file = 'name2_file.csv'

name1 = csv.DictReader(open(name1_file, 'rb'), delimiter=',', quotechar='"')


score_75_plus = []
name1_name =[]
name2_name =[]
name1_city = []
name2_city = []
name1_street = []
name2_street = []
name1_id = []
name2_id = []


for line in name1:
    name2 = csv.DictReader(open(name2_file, 'rb'), delimiter=',', quotechar='"')
    for line2 in name2:
        if line['City'] == line2['City'] and line['Street'] == line['Street']:
            partial_ratio = fuzz.partial_ratio(line['Name'], line2['Name'])
            if partial_ratio > 75:
                name1.append(line['Name'])
                name1_city.append(line['City'])
                name1_street.append(line['Street'])
                name2_name.append(line2['Name'])
                name2_city.append(line2['City'])
                name2_street.append(line2['Street'])
                score_75_plus.append(partial_ratio)
                name1_id.append(line['objectid']
                name2_id.append(line2['objectid']

big_test= zip(name1_name, name1_city, name1_street, name1_id, name2_name, name2_city, name2_street, name2_id, score_75_plus)
writer=csv.writer(open('big_test.csv', 'wb'))
writer.writerows(big_test)

但是,由於我的文件很大,我認為這將花費一些時間……也許是幾天。 我想提高效率,但還沒有弄清楚該怎么做。 到目前為止,我的想法是將字典重組為嵌套字典,以減少為了檢查城市和街道是否相同而必須循環通過的數據量。 我正在設想這樣的事情:

['San Francisco' : 
    {'Pearl': 
        {'City' :'San Francisco', 'Name':'Szn', 'id_number' : '1567', 'Street': 'Pearl'} }, 
'Boston' : 
    {'Pine': 
        {'City' :'Boston', 'Name':'Frd', 'id_number' : '1578', 'Street': 'Pine'}, 
    'Canyon': {'City' :'Boston', 'Name':'Bob', 'id_number' : '1572', 'Street': 'Canyon'} },
'Chicago' : 
    {'Spruce': 
        {'City' :'Chicago', 'Name':'Lizzy', 'id_number' : '1569', 'Street': 'Spruce'}, 
        {'City' :'Chicago', 'Name':'Bob', 'id_number' : '1571', 'Street': 'Spruce'} },
'Denver' :
    {'Spruce':
        {'City' :'Denver', 'Name':'Bob', 'id_number' : '1570', 'Street': 'Spruce'}},
'Boulder':
    {'Violet': 
        {'City' :'Boulder', 'Name':'Diana', 'id_number' : '1573', 'Street': 'Violet'}},
'Detroit':
    {'Grape': 
        {'City' :'Detroit', 'Name':'Bill', 'id_number' : '1574', 'Street': 'Grape'}}]

只需查看該城市中不同的城市和街道,即可決定是否應用fuzz.partial_ratio。 我使用defaultdict按城市將其拆分,但無法再次將其應用於街道。

city_dictionary = defaultdict(list)

for line in name1:
    city_dictionary[line['City']].append(line)

我已經看了這個答案,但是不知道如何實現。

對不起這么多細節,我不確定嵌套字典是必經之路,所以我想我應該介紹一下大圖。

您可以做的幾件事:

  1. 不要為第一個csv文件中的每一行重新打開第二個文件。 使用數據結構(可能是列表)來存儲所有信息並在內存中使用它。
  2. 分析您的代碼,以了解大部分時間都花在了哪里。
  3. 如果大部分時間都花在CPU上,請使用multiprocessing模塊來使用計算機上的所有內核,因為此處的任務似乎與上下文無關。
  4. 如果大多數時間都花在讀取文件(I / O)上,請在讀取文件時使用threading模塊進行一些處理。 您可能需要將文件分成較小的塊。

如果這樣做沒有幫助,那么我可以嘗試根據您的代碼添加更多內容。

編輯:

一次讀取第二個文件,而不是重新讀取第一個文件中的每一行的示例:

# read file once before the loop
file_2_dicts = list(csv.DictReader(open(name2_file, 'rb'), delimiter=',', quotechar='"'))
for line in name1:
    # remove old read and use in-memory dicts from first file
    # name2 = csv.DictReader(open(name2_file, 'rb'), delimiter=',', quotechar='"')
    name2 = file_2_dicts
    for line2 in name2:
        ...
        ...

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
4550    0.055    0.000    0.066    0.000 csv.py:100(next)
9098    0.006    0.000    0.006    0.000 csv.py:86(fieldnames)
4497409    3.845    0.000   54.221    0.000 difflib.py:154(__init__)
4497409    3.678    0.000   50.377    0.000 difflib.py:223(set_seqs)
4497409    3.471    0.000    3.471    0.000 difflib.py:235(set_seq1)
4497409    3.695    0.000   43.228    0.000 difflib.py:261(set_seq2)
4497409   29.130    0.000   39.533    0.000 difflib.py:306(__chain_b)
13356323   78.759    0.000  100.599    0.000 difflib.py:350(find_longest_match)
3123327    1.398    0.000    1.398    0.000 difflib.py:41(_calculate_ratio)
4497409   36.080    0.000  164.628    0.000 difflib.py:460(get_matching_blocks)
3123327    7.450    0.000  128.167    0.000 difflib.py:636(ratio)
7500936    1.673    0.000    1.673    0.000 difflib.py:658(<lambda>)
1374082   16.978    0.000  252.893    0.000 fuzz.py:57(partial_ratio)
1374082    1.172    0.000    1.647    0.000 utils.py:42(make_type_consistent)
3123327    2.587    0.000    4.260    0.000 {_functools.reduce}
23980904    7.633    0.000    7.633    0.000 {built-in method __new__ of type object at 0x100185f40}
4497410    6.525    0.000   16.009    0.000 {map}
1373764    0.496    0.000    0.496    0.000 {max}
32176130    3.231    0.000    3.231    0.000 {method '__contains__' of 'set' objects}
61813598    9.676    0.000    9.676    0.000 {method 'append' of 'list' objects}
72656176    7.728    0.000    7.728    0.000 {method 'get' of 'dict' objects}
13356323    5.311    0.000    5.311    0.000 {method 'pop' of 'list' objects}
33073067    4.927    0.000    4.927    0.000 {method 'setdefault' of 'dict' objects}
4497409    1.568    0.000    1.568    0.000 {method 'sort' of 'list' objects}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM