优化两个列表之间的元素明智的模糊匹配
Optimize element wise fuzzy match between two lists
我有两个不同格式的公司列表(较长列表中有 > 2k 个条目)需要统一。我知道这两种格式大约 80% 的时间共享一个存根,所以我使用模糊匹配来比较两个列表:
def get_fuzz_score(str1, str2):
from fuzzywuzzy import fuzz
partial_ratio = fuzz.partial_ratio(str1, str2)
return partial_ratio
a = ['Express Scripts', 'Catamaran Corp', 'Banmedica SA (96.7892%)', 'WebMD', 'ODC', 'Caremerge LLC (Stake%)']
b = ['Doctor on Demand', 'Catamaran', 'Express Scripts Holding Corp', 'ODC, Inc.', 'WebMD Health Services', 'Banmedica']
for i in b:
for j in a:
if get_fuzz_score(i, j) > 80:
# process
对于如何优化此任务以提高性能(例如,不必使用 2 个 for 循环)的想法,我将不胜感激。
我假设您同时安装了 fuzzywuzzy 和 python-Levenshtein。
第二个包的安装失败,因此我收到一条消息:
warnings.warn('Using slow pure-python SequenceMatcher. Install python-Levenshtein to remove this warning')
您可以使用 itertools.product 创建笛卡尔积:
from itertools import product
from fuzzywuzzy import fuzz
def get_fuzz_score(str1, str2):
partial_ratio = fuzz.partial_ratio(str1, str2)
return partial_ratio
a = ['Express Scripts', 'Catamaran Corp', 'Banmedica SA (96.7892%)', 'WebMD', 'ODC', 'Caremerge LLC (Stake%)']
b = ['Doctor on Demand', 'Catamaran', 'Express Scripts Holding Corp', 'ODC, Inc.', 'WebMD Health Services', 'Banmedica']
for first, second in product(a, b):
if get_fuzz_score(first, second) > 80:
# process
如果您的功能 get_fuzz_score 没有增长,您可以将其废弃:
from itertools import product
from fuzzywuzzy import fuzz #
a = ['Express Scripts', 'Catamaran Corp', 'Banmedica SA (96.7892%)', 'WebMD', 'ODC', 'Caremerge LLC (Stake%)']
b = ['Doctor on Demand', 'Catamaran', 'Express Scripts Holding Corp', 'ODC, Inc.', 'WebMD Health Services', 'Banmedica']
for first, second in product(a, b):
if fuzz.partial_ratio(first, second) > 80:
pass # process
首先,我会将导入 from fuzzywuzzy import fuzz
从函数移动到文件的开头。
接下来,您似乎想要检查每个元素,所以您无论如何都要比较 all2all,但我没有看到简单的解决方法。
如果数据是 'nice',那么您可以进行一些简单的启发式操作,例如在第一个字母上(来自您发布的示例 - 但这取决于数据)。
此致
P.s。如果我的分数足够高,我会发表评论。
fuzzywuzzy
提供了一个 process.extract*
系列函数来帮助解决这个问题,例如:
from fuzzywuzzy import process
a = ['Express Scripts', 'Catamaran Corp', 'Banmedica SA (96.7892%)', 'WebMD', 'ODC', 'Caremerge LLC (Stake%)']
b = ['Doctor on Demand', 'Catamaran', 'Express Scripts Holding Corp', 'ODC, Inc.', 'WebMD Health Services', 'Banmedica']
for name in a:
print(name, process.extract(name, b, limit=3))
将打印出 a
中的每个名称以及 b
中的三个最佳匹配项。
这仍然是 O(n**2)
,但是因为这个库是开源代码,你可以看到 extract
是如何定义的,也许只做一次 preprocessing 而不是每次希望加快速度
我有两个不同格式的公司列表(较长列表中有 > 2k 个条目)需要统一。我知道这两种格式大约 80% 的时间共享一个存根,所以我使用模糊匹配来比较两个列表:
def get_fuzz_score(str1, str2):
from fuzzywuzzy import fuzz
partial_ratio = fuzz.partial_ratio(str1, str2)
return partial_ratio
a = ['Express Scripts', 'Catamaran Corp', 'Banmedica SA (96.7892%)', 'WebMD', 'ODC', 'Caremerge LLC (Stake%)']
b = ['Doctor on Demand', 'Catamaran', 'Express Scripts Holding Corp', 'ODC, Inc.', 'WebMD Health Services', 'Banmedica']
for i in b:
for j in a:
if get_fuzz_score(i, j) > 80:
# process
对于如何优化此任务以提高性能(例如,不必使用 2 个 for 循环)的想法,我将不胜感激。
我假设您同时安装了 fuzzywuzzy 和 python-Levenshtein。 第二个包的安装失败,因此我收到一条消息:
warnings.warn('Using slow pure-python SequenceMatcher. Install python-Levenshtein to remove this warning')
您可以使用 itertools.product 创建笛卡尔积:
from itertools import product
from fuzzywuzzy import fuzz
def get_fuzz_score(str1, str2):
partial_ratio = fuzz.partial_ratio(str1, str2)
return partial_ratio
a = ['Express Scripts', 'Catamaran Corp', 'Banmedica SA (96.7892%)', 'WebMD', 'ODC', 'Caremerge LLC (Stake%)']
b = ['Doctor on Demand', 'Catamaran', 'Express Scripts Holding Corp', 'ODC, Inc.', 'WebMD Health Services', 'Banmedica']
for first, second in product(a, b):
if get_fuzz_score(first, second) > 80:
# process
如果您的功能 get_fuzz_score 没有增长,您可以将其废弃:
from itertools import product
from fuzzywuzzy import fuzz #
a = ['Express Scripts', 'Catamaran Corp', 'Banmedica SA (96.7892%)', 'WebMD', 'ODC', 'Caremerge LLC (Stake%)']
b = ['Doctor on Demand', 'Catamaran', 'Express Scripts Holding Corp', 'ODC, Inc.', 'WebMD Health Services', 'Banmedica']
for first, second in product(a, b):
if fuzz.partial_ratio(first, second) > 80:
pass # process
首先,我会将导入 from fuzzywuzzy import fuzz
从函数移动到文件的开头。
接下来,您似乎想要检查每个元素,所以您无论如何都要比较 all2all,但我没有看到简单的解决方法。
如果数据是 'nice',那么您可以进行一些简单的启发式操作,例如在第一个字母上(来自您发布的示例 - 但这取决于数据)。
此致
P.s。如果我的分数足够高,我会发表评论。
fuzzywuzzy
提供了一个 process.extract*
系列函数来帮助解决这个问题,例如:
from fuzzywuzzy import process
a = ['Express Scripts', 'Catamaran Corp', 'Banmedica SA (96.7892%)', 'WebMD', 'ODC', 'Caremerge LLC (Stake%)']
b = ['Doctor on Demand', 'Catamaran', 'Express Scripts Holding Corp', 'ODC, Inc.', 'WebMD Health Services', 'Banmedica']
for name in a:
print(name, process.extract(name, b, limit=3))
将打印出 a
中的每个名称以及 b
中的三个最佳匹配项。
这仍然是 O(n**2)
,但是因为这个库是开源代码,你可以看到 extract
是如何定义的,也许只做一次 preprocessing 而不是每次希望加快速度