Хотя комментарий @Igle действительно решает эту конкретную проблему, я хочу подчеркнуть, что это узкое решение, которое не обязательно будет работать для всего. Fuzzywuzzy имеет несколько счетчиков, которые используют алгоритм расстояния Левенштейна в сочетании с другой логикой для сравнения строк. Средство оценки по умолчанию, fuzz.WRatio, сравнивает оценку соответствия алгоритма прямого расстояния Левенштейна (fuzz.ratio) с другими вариантами и возвращает наилучшее совпадение из всех средств оценки. Это больше, чем просто это, в том числе дополнительная логика для взвешивания оценок с помощью разных методов, если вам интересно, я предлагаю посмотреть исходный код fuzz.WRatio.
Чтобы увидеть, что происходит в вашем случае, вы можете сравнить оценки для всех вариантов в разных счетчиках, немного адаптировав последние строки вашего кода:
Для token_set_ratio:
for i in names:
s = process.extract(i, choices,scorer=fuzz.token_set_ratio)
print(s, i)
[('Gonzalez Ryan', 89), ('Gonzalez Eddy', 89), ('Kody Clemens', 27), ('Kacy Clemens', 27)] Gonzalez, E.
[('Gonzalez Ryan', 89), ('Gonzalez Eddy', 89), ('Kody Clemens', 27), ('Kacy Clemens', 27)] Gonzalez, R.
[('Kody Clemens', 91), ('Kacy Clemens', 82), ('Gonzalez Ryan', 26), ('Gonzalez Eddy', 26)] Clemens, Ko.
[('Kacy Clemens', 91), ('Kody Clemens', 82), ('Gonzalez Ryan', 35), ('Gonzalez Eddy', 26)] Clemens, Ka.
Для token_sort_ratio:
for i in names:
s = process.extract(i, choices,scorer=fuzz.token_sort_ratio)
print(s, i)
[('Gonzalez Eddy', 87), ('Gonzalez Ryan', 70), ('Kody Clemens', 27), ('Kacy Clemens', 27)] Gonzalez, E.
[('Gonzalez Ryan', 87), ('Gonzalez Eddy', 70), ('Kody Clemens', 27), ('Kacy Clemens', 27)] Gonzalez, R.
[('Kody Clemens', 91), ('Kacy Clemens', 82), ('Gonzalez Ryan', 26), ('Gonzalez Eddy', 26)] Clemens, Ko.
[('Kacy Clemens', 91), ('Kody Clemens', 82), ('Gonzalez Ryan', 35), ('Gonzalez Eddy', 26)] Clemens, Ka.
Хотя token_sort_ratio показывает явное выигрышное совпадение, token_set_ratio возвращает более высокие баллы, и именно так fuzz.WRatio выбирает, какой результат он возвращает. Еще одна важная проблема заключается в том, что когда у вас есть такие похожие запросы и варианты выбора, порядок, в котором они сравниваются, начинает иметь значение. Например, когда я запускаю тот же самый код, что и выше, но меняю порядок списка вариантов, мы получаем «Gonzalez Eddy» для обоих:
for i in names:
s = process.extract(i, choices[::-1],scorer=fuzz.token_set_ratio)
print(s, i)
[('Gonzalez Eddy', 89), ('Gonzalez Ryan', 89), ('Kacy Clemens', 27), ('Kody Clemens', 27)] Gonzalez, E.
[('Gonzalez Eddy', 89), ('Gonzalez Ryan', 89), ('Kacy Clemens', 27), ('Kody Clemens', 27)] Gonzalez, R.
[('Kody Clemens', 91), ('Kacy Clemens', 82), ('Gonzalez Eddy', 26), ('Gonzalez Ryan', 26)] Clemens, Ko.
[('Kacy Clemens', 91), ('Kody Clemens', 82), ('Gonzalez Ryan', 35), ('Gonzalez Eddy', 26)] Clemens, Ka.
Я предполагаю, что правильное совпадение на самом деле имеет более высокий балл, но «Эдди» и «Райан» достаточно близки к тому, чтобы оба раунда получили одинаковый окончательный результат.
Способы, которыми я справлялся с подобными проблемами в прошлом:
- Используйте экстракт вместо ExtractOne (как я делал в примерах выше)
- Обрабатывайте одни и те же запросы/выборы с несколькими оценщиками (ratio, token_set_ratio, token_sort_ratio) и используйте средневзвешенное значение этих оценок, чтобы выбрать наилучшее совпадение.
- Скорректируйте исходный код fuzzywuzzy, чтобы включить пользовательский вес или удалить округление.
person
YG14
schedule
08.11.2017
s = process.extractOne(i, choices, scorer=fuzz.token_sort_ratio)
работает - person Igle   schedule 13.09.2017