【问题标题】:Better Approach than FuzzyWuzzy?比 FuzzyWuzzy 更好的方法?
【发布时间】:2018-07-31 23:56:34
【问题描述】:

我得到的结果是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

我希望第一对(丹尼尔对丹尼尔威廉)比第二对(丹尼尔对大卫)更好。

有没有比fuzzywuzzy更好的方法在这里使用?

【问题讨论】:

    标签: python fuzzy-search fuzzywuzzy


    【解决方案1】:

    对于您的示例,您可以使用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
    

    【讨论】:

      【解决方案2】:

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

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

      所有单词的身份匹配得分为 1 (100%)。您的比较得分如下:

    • 丹尼尔·卡特赖特与丹尼尔·威廉·卡特赖特 = (2/2 + 2/3)/2 = (5/3)/2 = 0.83
    • DANIEL CARTWRIGHT 与 DAVID CARTWRIGHT = (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
      
    • 【讨论】:

        猜你喜欢
        • 2017-06-26
        • 2016-12-23
        • 2019-03-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多