[英]How to fuzzy match two lists in Python
我有兩個列表: ref_list
和inp_list
。 如何利用 FuzzyWuzzy 從參考列表中匹配輸入列表?
inp_list = pd.DataFrame(['ADAMS SEBASTIAN', 'HAIMBILI SEUN', 'MUTESI
JOHN', 'SHEETEKELA MATT', 'MUTESI JOHN KUTALIKA',
'ADAMS SEBASTIAN HAUSIKU', 'PETERS WILSON',
'PETERS MARIO', 'SHEETEKELA MATT NICKY'],
columns =['Names'])
ref_list = pd.DataFrame(['ADAMS SEBASTIAN HAUSIKU', 'HAIMBILI MIKE', 'HAIMBILI SEUN', 'MUTESI JOHN
KUTALIKA', 'PETERS WILSON MARIO', 'SHEETEKELA MATT NICKY MBILI'], columns =
['Names'])
經過一些研究,我修改了一些我在 inte.net 上找到的代碼。 這些代碼的問題 - 它們在小樣本量上工作得很好。 在我的例子中, inp_list
和ref_list
的長度分別為 29k 和 18k,運行需要一天多的時間。
下面是代碼,首先定義了一個 helper function。
def match_term(term, inp_list, min_score=0):
# -1 score in case I don't get any matches
max_score = -1
# return empty for no match
max_name = ''
# iterate over all names in the other
for term2 in inp_list:
# find the fuzzy match score
score = fuzz.token_sort_ratio(term, term2)
# checking if I am above my threshold and have a better score
if (score > min_score) & (score > max_score):
max_name = term2
max_score = score
return (max_name, max_score)
# list for dicts for easy dataframe creation
dict_list = []
#iterating over the sales file
for name in inp_list:
#use the defined function above to find the best match, also set the threshold to a chosen #
match = match_term(name, ref_list, 94)
#new dict for storing data
dict_ = {}
dict_.update({'passenger_name': name})
dict_.update({'match_name': match[0]})
dict_.update({'score': match[1]})
dict_list.append(dict_)
這些代碼在哪里可以改進以順利運行並可能避免評估已經評估的項目?
您可以嘗試對操作進行矢量化,而不是在循環中評估分數。
制作一個df
,其中第一個 col ref
是ref_list
,第二個 col inp_list
是inp
中的每個名稱。 然后調用df.apply(lambda row:process.extractOne(row['inp'], row['ref']), axis=1)
。 最后,您將在ref_list
中為inp_list
中的每個名稱獲得最佳匹配名稱和得分。
您使用的措施在計算上要求很高,並且有許多對字符串。 fuzzywuzzy
,您還可以嘗試使用名為string-grouper
grouper 的庫,它利用更快的 Tf-idf 方法和余弦相似度度量來查找相似詞。 舉個例子:
import random, string, time
import pandas as pd
from string_grouper import match_strings
alphabet = list(string.ascii_lowercase)
from_r, to_r = 0, len(alphabet)-1
random_strings_1 = ["".join(alphabet[random.randint(from_r, to_r)]
for i in range(6)) for j in range(5000)]
random_strings_2 = ["".join(alphabet[random.randint(from_r, to_r)]
for i in range(6)) for j in range(5000)]
series_1 = pd.Series(random_strings_1)
series_2 = pd.Series(random_strings_2)
t_1 = time.time()
matches = match_strings(series_1, series_2,
min_similarity=0.6)
t_2 = time.time()
print(t_2 - t_1)
print(matches)
進行 25.000.000 次比較只需要不到一秒鍾的時間:要對庫進行更有用的測試,請看這里: https://bergvca.github.io/2017/10/14/super-fast-string-matching.html據稱
“使用這種方法可以僅使用雙核筆記本電腦在 42 分鍾內搜索一組 663,000 個公司名稱中的近似重復項”。
要進一步調整您的匹配算法,請查看**kwargs arguments ,您可以將其提供給上面的match_strings
function。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.