web-dev-qa-db-fra.com

Quand utiliser quelle fonction fuzz pour comparer 2 chaînes

J'apprends fuzzywuzzy en Python.

Je comprends le concept de fuzz.ratio, fuzz.partial_ratio, fuzz.token_sort_ratio et fuzz.token_set_ratio. Ma question est quand utiliser quelle fonction?

  • Dois-je d'abord vérifier la longueur des 2 chaînes, disons si elles ne sont pas similaires, puis exclure fuzz.partial_ratio?
  • Si la longueur des 2 cordes est similaire, j'utiliserai fuzz.token_sort_ratio?
  • Dois-je toujours utiliser fuzz.token_set_ratio?

Tout le monde sait quels critères SeatGeek utilise?

J'essaie de créer un site Web immobilier, en pensant à utiliser fuzzywuzzy pour comparer les adresses.

26
Pot

Grande question.

Je suis ingénieur chez SeatGeek, donc je pense que je peux vous aider ici. Nous avons un grand article de blog qui explique assez bien les différences, mais je peux résumer et offrir un aperçu de la façon dont nous utilisons les différents types.

Aperçu

Sous le capot, chacune des quatre méthodes calcule la distance d'édition entre un certain ordre des jetons dans les deux chaînes d'entrée. Cela se fait en utilisant le difflib.ratio fonction qui sera :

Retourne une mesure de la similitude des séquences (float in [0,1]).

Où T est le nombre total d'éléments dans les deux séquences, et M est le nombre de correspondances, c'est 2,0 * M/T. Notez que c'est 1 si les séquences sont identiques et 0 si elles n'ont rien en commun.

Les quatre méthodes floues floues appellent difflib.ratio sur différentes combinaisons des chaînes d'entrée.

fuzz.ratio

Facile. Appelle simplement difflib.ratio sur les deux chaînes d'entrée ( code ).

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

fuzz.partial_ratio

Tente de mieux prendre en compte les correspondances de chaînes partielles. Appelle ratio en utilisant la chaîne la plus courte (longueur n) contre toutes les sous-chaînes de longueur n de la plus grande chaîne et renvoie le score le plus élevé ( code ).

Notez ici que "YANKEES" est la chaîne la plus courte (longueur 7), et nous exécutons le rapport avec "YANKEES" contre toutes les sous-chaînes de longueur 7 de "NEW YORK YANKEES" (ce qui comprendrait la vérification avec "YANKEES", une correspondance à 100% ):

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

fuzz.token_sort_ratio

Tente de rendre compte de chaînes similaires hors service. Appelle ratio sur les deux chaînes après avoir trié les jetons dans chaque chaîne ( code ). Remarquez ici fuzz.ratio et fuzz.partial_ratio les deux échouent, mais une fois que vous avez trié les jetons, c'est une correspondance à 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

Tente d'exclure les différences dans les chaînes. Appelle le ratio sur trois ensembles de sous-chaînes particuliers et renvoie le max ( code ):

  1. intersection uniquement et l'intersection avec le reste de la chaîne un
  2. intersection uniquement et l'intersection avec le reste de la chaîne deux
  3. intersection avec le reste d'un et intersection avec le reste de deux

Notez qu'en divisant l'intersection et les restes des deux chaînes, nous tenons compte de la similitude et de la différence des deux chaînes:

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

Application

C'est là que la magie opère. Chez SeatGeek, nous créons essentiellement un score vectoriel avec chaque ratio pour chaque point de données (lieu, nom de l'événement, etc.) et nous l'utilisons pour informer les décisions programmatiques de similitude qui sont spécifiques à notre domaine de problème.

Cela étant dit, la vérité dit qu'il ne semble pas que FuzzyWuzzy soit utile pour votre cas d'utilisation. Il sera extrêmement difficile de déterminer si deux adresses sont similaires. Considérez deux adresses possibles pour le siège de SeatGeek: "235 Park Ave Floor 12" et "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 donne à ces chaînes un score de correspondance élevé, mais une adresse est notre bureau réel près de Union Square et l'autre est de l'autre côté de Grand Central.

Pour votre problème, il vaut mieux utiliser Google Geocoding API .

55
Rick Hanlon II

Depuis juin 2017, fuzzywuzzy inclut également d'autres fonctions de comparaison. Voici un aperçu de celles qui manquent dans la réponse acceptée (tirée du code source ):

fuzz.partial_token_sort_ratio

Même algorithme que dans token_sort_ratio, mais au lieu d'appliquer ratio après le tri des jetons, utilise 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

Même algorithme que dans token_set_ratio, mais au lieu d'appliquer ratio aux ensembles de jetons, utilise 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

Juste des emballages autour fuzz.ratio avec quelques validations et courts-circuits, inclus ici pour être complet. UQRatio est une version unicode de QRatio.

fuzz.WRatio

Une tentative de pondération (le nom signifie "ratio pondéré") résulte de différents algorithmes pour calculer le "meilleur" score. Description du code source:

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

Version Unicode de WRatio.

9
Dennis Golomazov