Подтвердить что ты не робот

Когда использовать функцию fuzz для сравнения 2 строк

Я изучаю fuzzywuzzy в Python.

Я понимаю понятия fuzz.ratio, fuzz.partial_ratio, fuzz.token_sort_ratio и fuzz.token_set_ratio. У меня вопрос, когда использовать какую функцию?

  • Должен ли я сначала проверить длину 2 строк, скажем, если они не похожи, то исключить fuzz.partial_ratio?
  • Если длина двух строк одинакова, я буду использовать fuzz.token_sort_ratio?
  • Должен ли я всегда использовать fuzz.token_set_ratio?

Кто-нибудь знает, какие критерии использует SeatGeek?

Я пытаюсь создать сайт по недвижимости, думая использовать fuzzywuzzy для сравнения адресов.

4b9b3361

Ответ 1

Отличный вопрос.

Я инженер в SeatGeek, поэтому я думаю, что могу помочь здесь. У нас отличное сообщение в блоге, которое объясняет различия довольно хорошо, но я могу обобщить и дать некоторое представление о том, как мы используем разные типы.

обзор

Под капотом каждый из четырех методов вычисляет расстояние редактирования между некоторым упорядочением токенов в обеих входных строках. Это выполняется с difflib.ratio функции difflib.ratio которая будет:

Возвратите меру сходства последовательностей (float в [0,1]).

Где T - общее количество элементов в обеих последовательностях, а M - количество совпадений, это 2.0 * M/T. Обратите внимание, что это 1, если последовательности идентичны, и 0, если они не имеют ничего общего.

Четыре метода fuzzywuzzy вызывают difflib.ratio для разных комбинаций входных строк.

fuzz.ratio

Просто. Просто вызывает difflib.ratio на двух входных строках (код).

fuzz.ratio("NEW YORK METS", "NEW YORK MEATS")
> 96

fuzz.partial_ratio

Попытки объяснить частичную строку соответствуют лучше. ratio вызовов с использованием кратчайшей строки (длина n) по всем подстрокам n-длины большей строки и возвращает наивысший балл (код).

Обратите внимание, что "YANKEES" - это кратчайшая строка (длина 7), и мы управляем соотношением с "YANKEES" против всех подстрок длины 7 "NEW YORK YANKEES" (который будет включать проверку против "YANKEES", 100% -ную совпадение ):

fuzz.ratio("YANKEES", "NEW YORK YANKEES")
> 60
fuzz.partial_ratio("YANKEES", "NEW YORK YANKEES")
> 100

fuzz.token_sort_ratio

Попытки вывести из строя аналогичные строки. ratio вызовов по обеим строкам после сортировки токенов в каждой строке (код). Обратите внимание, что fuzz.ratio и fuzz.partial_ratio оба не fuzz.partial_ratio, но как только вы сортируете токены, это соответствует 100%:

fuzz.ratio("New York Mets vs Atlanta Braves", "Atlanta Braves vs New York Mets")
> 45
fuzz.partial_ratio("New York Mets vs Atlanta Braves", "Atlanta Braves vs New York Mets")
> 45
fuzz.token_sort_ratio("New York Mets vs Atlanta Braves", "Atlanta Braves vs New York Mets")
> 100

fuzz.token_set_ratio

Попытки исключить различия в строках. Соотношение вызовов на трех конкретных подстроках и возвращает max (код):

  1. только пересечение и пересечение с остатком строки 1
  2. пересечение и пересечение с остатком второй строки
  3. пересечение с остатком одного и пересечение с остатком двух

Обратите внимание, что, разделив пересечение и остатки двух строк, мы учитываем как сходные, так и разные две строки:

fuzz.ratio("mariners vs angels", "los angeles angels of anaheim at seattle mariners")
> 36
fuzz.partial_ratio("mariners vs angels", "los angeles angels of anaheim at seattle mariners")
> 61
fuzz.token_sort_ratio("mariners vs angels", "los angeles angels of anaheim at seattle mariners")
> 51
fuzz.token_set_ratio("mariners vs angels", "los angeles angels of anaheim at seattle mariners")
> 91

заявка

Здесь происходит волшебство. В SeatGeek по существу мы создаем векторную оценку с каждым соотношением для каждой точки данных (место проведения, название события и т.д.) И используем это для информирования о программных решениях сходства, которые характерны для нашей проблемной области.

Сказанное, правда, сказал, что это не похоже, что FuzzyWuzzy полезен для вашего случая использования. Это будет потрясающе плохо при определении того, являются ли два адреса похожими. Рассмотрим два возможных адреса для штаб-квартиры SeatGeek: "235 Park Ave Floor 12" и "235 Park Ave S. Floor 12":

fuzz.ratio("235 Park Ave Floor 12", "235 Park Ave S. Floor 12")
> 93
fuzz.partial_ratio("235 Park Ave Floor 12", "235 Park Ave S. Floor 12")
> 85
fuzz.token_sort_ratio("235 Park Ave Floor 12", "235 Park Ave S. Floor 12")
> 95
fuzz.token_set_ratio("235 Park Ave Floor 12", "235 Park Ave S. Floor 12")
> 100

FuzzyWuzzy дает этим строкам высокий балл матча, но один адрес - наш фактический офис возле Юнион-сквер, а другой находится на другой стороне Гранд-Центра.

Для вашей проблемы вам будет лучше использовать Google Geocoding API.

Ответ 2

По состоянию на июнь 2017 года, fuzzywuzzy также включает в себя некоторые другие функции сравнения. Вот краткий обзор недостающих из принятого ответа (взятых из исходного кода):

fuzz.partial_token_sort_ratio

Тот же алгоритм, что и в token_sort_ratio, но вместо применения ratio после сортировки токенов использует partial_ratio.

fuzz.token_sort_ratio("New York Mets vs Braves", "Atlanta Braves vs New York Mets")
> 85
fuzz.partial_token_sort_ratio("New York Mets vs Braves", "Atlanta Braves vs New York Mets")
> 100    
fuzz.token_sort_ratio("React.js framework", "React.js")
> 62
fuzz.partial_token_sort_ratio("React.js framework", "React.js")
> 100

fuzz.partial_token_set_ratio

Тот же алгоритм, что и в token_set_ratio, но вместо применения ratio к наборам токенов использует partial_ratio.

fuzz.token_set_ratio("New York Mets vs Braves", "Atlanta vs New York Mets")
> 82
fuzz.partial_token_set_ratio("New York Mets vs Braves", "Atlanta vs New York Mets")
> 100    
fuzz.token_set_ratio("React.js framework", "Reactjs")
> 40
fuzz.partial_token_set_ratio("React.js framework", "Reactjs")
> 71   

fuzz.QRatio, fuzz.UQRatio

Просто fuzz.ratio вокруг fuzz.ratio с некоторой валидацией и короткой замыканием, включенные здесь для полноты. UQRatio - это QRatio версия QRatio.

fuzz.WRatio

Попытка веса (название означает "взвешенное соотношение") получается из разных алгоритмов для вычисления "лучшего" балла. Описание из исходного кода:

1. Take the ratio of the two processed strings (fuzz.ratio)
2. Run checks to compare the length of the strings
    * If one of the strings is more than 1.5 times as long as the other
      use partial_ratio comparisons - scale partial results by 0.9
      (this makes sure only full results can return 100)
    * If one of the strings is over 8 times as long as the other
      instead scale by 0.6
3. Run the other ratio functions
    * if using partial ratio functions call partial_ratio,
      partial_token_sort_ratio and partial_token_set_ratio
      scale all of these by the ratio based on length
    * otherwise call token_sort_ratio and token_set_ratio
    * all token based comparisons are scaled by 0.95
      (on top of any partial scalars)
4. Take the highest value from these results
   round it and return it as an integer.

fuzz.UWRatio

Unicode версия WRatio.