优化两个列表之间的逐元素模糊匹配

时间:2019-10-21 15:37:13

标签: python fuzzy-search fuzzywuzzy

我有两个公司的列表(较长列表中有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)。

3 个答案:

答案 0 :(得分:3)

首先,我将导入from fuzzywuzzy import fuzz从函数移至文件的开头。

接下来,您似乎想要检查每个元素,因此无论如何都比较all2all,我看不到任何简单的解决方法。

如果数据“不错”,则可以执行一些简单的启发式操作,例如(您发布的示例中的第一个字母-但这取决于数据)。

最诚挚的问候

P.s。如果我的分数足够高,我会发表评论。

答案 1 :(得分:2)

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,而不是每次都希望这样做会加快速度事情很多了

答案 2 :(得分:1)

我假设您同时安装了Fuzzywuzzy和python-Levenshtein。 第二个软件包的安装失败,因此我收到一条消息:

  

warnings.warn(“使用慢速纯Python SequenceMatcher。安装python-Levenshtein删除此警告”)

您可以使用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