比FuzzyWuzzy更好的方法?

时间:2018-07-31 23:56:35

标签: python fuzzy-search fuzzywuzzy

我得到的结果模糊不清,效果不理想。如果中间有多余的单词,则由于levenshtein的差异,分数会更低。

示例:

from fuzzywuzzy import fuzz

score = fuzz.ratio('DANIEL CARTWRIGHT', 'DANIEL WILLIAM CARTWRIGHT')
print(score)
score = fuzz.ratio('DANIEL CARTWRIGHT', 'DAVID CARTWRIGHT')
print(score)

score = fuzz.partial_ratio('DANIEL CARTWRIGHT', 'DANIEL WILLIAM CARTWRIGHT')
print(score)
score = fuzz.partial_ratio('DANIEL CARTWRIGHT', 'DAVID CARTWRIGHT')
print(score)

结果: 81 85 71 81

我正在寻找第一对(丹尼尔vs丹尼尔·威廉姆)比第二对(丹尼尔vs大卫)更好的比赛。

在这里使用比模糊模糊更好的方法吗?

2 个答案:

答案 0 :(得分:4)

例如,您可以使用token_set_ratio。代码文档说,它采用令牌与剩余令牌的交集之比。

from fuzzywuzzy import fuzz

score = fuzz.token_set_ratio('DANIEL CARTWRIGHT', 'DANIEL WILLIAM CARTWRIGHT')
print(score)
score = fuzz.token_set_ratio('DANIEL CARTWRIGHT', 'DAVID CARTWRIGHT')
print(score)

结果:

100
85

答案 1 :(得分:0)

我在使用 FuzzyWuzzy 将一个名称列表与另一个名称列表进行比较以识别列表之间的匹配时遇到了类似的挑战。 FuzzyWuzzy token_set_ratio 记分器对我不起作用,因为以您的示例为例,将“DANIEL CARTWRIGHT”与“DANIEL WILLIAM CARTWRIGHT”和“DANIEL WILLIAM CARTWRIGHT”与“DANIEL WILLIAM CARTWRIGHT”进行比较(3 个单词中的 2 个与 DANIEL WILLIAM CARTWRIGHT 的部分匹配) 3 个单词中 3 个的身份匹配)都产生 100% 的分数。对我来说,匹配 3 个单词需要得分高于匹配 2 个 3 的得分。

我最终以一种类似词袋的方法使用了 nltk。下面代码中的算法将多词名称转换为不同词(标记)的列表,并对一个列表中的词与另一个列表的匹配进行计数,并将计数归一化为每个列表中的词数。因为 True = 1 和 False = 0,所以 sum() 过度测试元素是否在列表中非常适合 count the elements of one list in another list

所有单词的同一性匹配得分为 1 (100%)。比较的评分方法如下:

  • 丹尼尔·卡特赖特 vs. 丹尼尔·威廉·卡特赖特 = (2/2 + 2/3)/2 = (5/3)/2 = 0.83
  • 丹尼尔·卡特赖特 vs. 大卫·卡特赖特 = (1/2 + 1/2)/2 = 1/2 = 0.5
    请注意,我的方法忽略了词序,这在我的情况下是不需要的。
    import nltk
    
    s1 = 'DANIEL CARTWRIGHT'
    s2 = ['DANIEL WILLIAM CARTWRIGHT', 'DAVID CARTWRIGHT']
    
    def myScore(lst1, lst2):
        # calculate score for comparing lists of words
        c = sum(el in lst1 for el in lst2)
        if (len(lst1) == 0 or len(lst2) == 0):
            retval = 0.0
        else:
            retval = 0.5 * (c/len(lst1) + c/len(lst2))
        
        return retval
    
    tokens1 = nltk.word_tokenize(s1)
    
    for s in s2:
        tokens2 = nltk.word_tokenize(s)
        score = myScore(tokens1, tokens2)
        print(' vs. '.join([s1, s]), ":", str(score))
    

    输出:

    DANIEL CARTWRIGHT vs. DANIEL WILLIAM CARTWRIGHT : 0.8333333333333333
    DANIEL CARTWRIGHT vs. DAVID CARTWRIGHT : 0.5