<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Naomi Kriger</title>
    <description>The latest articles on DEV Community by Naomi Kriger (@naomikr).</description>
    <link>https://dev.to/naomikr</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F558568%2Ffd0ab02b-ec7f-4875-83c6-761ecdd9f03c.jpeg</url>
      <title>DEV Community: Naomi Kriger</title>
      <link>https://dev.to/naomikr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/naomikr"/>
    <language>en</language>
    <item>
      <title>FuzzyWuzzy — the Before and After</title>
      <dc:creator>Naomi Kriger</dc:creator>
      <pubDate>Wed, 13 Jan 2021 12:50:49 +0000</pubDate>
      <link>https://dev.to/behalf/fuzzywuzzy-the-before-and-after-46nm</link>
      <guid>https://dev.to/behalf/fuzzywuzzy-the-before-and-after-46nm</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3OiccRla--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/6016/1%2AjM7z8ZZYLcsCeUS6oeC2PQ.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3OiccRla--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/6016/1%2AjM7z8ZZYLcsCeUS6oeC2PQ.jpeg" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the previous &lt;a href="https://dev.to/behalf/comparing-strings-is-easy-with-fuzzywuzzy-5ck9"&gt;article&lt;/a&gt;, I introduced FuzzyWuzzy library which calculates a 0–100 matching score for a pair of strings. The different FuzzyWuzzy functions enable us to choose the one that would most accurately fit our needs.&lt;/p&gt;

&lt;p&gt;However, conducting a successful project is much more than just calculating scores. We need to clean the data before we start working on it, choose the best method to calculate our scores, learn how to work not only with a pair of strings but with tables of data, and eventually know how to use the scores we received to make the most out of our results.&lt;/p&gt;

&lt;p&gt;So, without further ado, let’s dive into some best practices we should be familiar with.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using a Table With Pandas In order To Compare Multiple Strings
&lt;/h2&gt;

&lt;p&gt;As discussed earlier, FuzzyWuzzy functions calculate matching scores for two strings. But when working with “real life” data, we will probably want to compare at least two sets of strings. This means working with a table, or when speaking in Pandas terms — working with DataFrames.&lt;/p&gt;

&lt;p&gt;A good table will resemble this one:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3VRKY8vB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/781/0%2AAS-cveFs4yX3-Pq1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3VRKY8vB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/781/0%2AAS-cveFs4yX3-Pq1" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The table above contains two comparison columns, each with a relevant header, where the strings to be compared are in parallel rows.&lt;/p&gt;

&lt;p&gt;Given such a dataset, we can read the table to a DataFrame using a relevant function. The example below reads directly from a CSV, but if you are interested in using other formats — you can check out the following &lt;a href="https://pandas.pydata.org/pandas-docs/stable/reference/io.html"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&amp;gt;&amp;gt;&amp;gt; &lt;em&gt;my_data_frame = pd.read_csv("my_folder/my_file_name.csv")&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Preprocessing — Cleaning the Data Before Analysis
&lt;/h2&gt;

&lt;p&gt;Before we choose our FuzzyWuzzy function and start comparing strings, we want to clean the data to ensure that our results will be as accurate as possible.&lt;/p&gt;

&lt;p&gt;Cleaning the data means removing irrelevant strings, and thus improving the functions’ performance.&lt;/p&gt;

&lt;p&gt;For example, let’s assume we compare strings of two addresses, where one address is “Joe Boulevard” and the other is “Jule Boulevard”. The matching score will be relatively high, but mostly due to the existence of “Boulevard” in both strings. Removing it and recalculating will result in a much lower matching score:&lt;/p&gt;

&lt;p&gt;&amp;gt;&amp;gt;&amp;gt; fuzz.ratio(“Joe Boulevard”, “Jule Boulevard”)&lt;br&gt;
89&lt;br&gt;
&amp;gt;&amp;gt;&amp;gt; fuzz.ratio(“Joe”, “Jule”)&lt;br&gt;
57&lt;/p&gt;

&lt;p&gt;The type of cleaning required for your data depends on your domain.&lt;br&gt;
We saw an example of the required cleaning for addresses. Similarly, when comparing phone numbers — we will probably want to remove parentheses and dashes that have no added value. It is also recommended to normalize all of your strings to lowercase since some FuzzyWuzzy functions treat differently-capitalized letters as different strings.&lt;br&gt;
So, look at your data, and decide what should be modified in order to make it clean and ready for processing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Pre-Processing — Let’s Get Technical
&lt;/h2&gt;

&lt;p&gt;Now, let’s define a function with the relevant logic, and iteratively run it on each of the relevant columns in the DataFrame.&lt;/p&gt;

&lt;p&gt;** The example below was simplified in order to keep the explanation clear. For best results, it is recommended to use regular expressions (regex) which is beyond the scope of this article. Note that &lt;em&gt;strings_to_remove&lt;/em&gt;, in its current form, may lead to imperfect results after the cleanup.&lt;/p&gt;

&lt;p&gt;&amp;gt;&amp;gt;&amp;gt; strings_to_remove = [' ave ', ' ave. ', 'avenue', ' lane ', ' ln', 'blvd', 'boulevard', ' rd. ', 'road', 'street', ' st. ', 'str ', ' dr. ',  'drive', ' apt ', 'apartment', 'valley', 'city', '.', ',']&lt;/p&gt;

&lt;p&gt;&amp;gt;&amp;gt;&amp;gt; comparison_table =&lt;br&gt;
    comparison_table.astype(str).apply(lambda x: x.str.lower())&amp;gt;&amp;gt;&amp;gt; for current_string in strings_to_remove:&lt;br&gt;
        comparison_table = comparison_table.astype(str).apply(&lt;br&gt;
           lambda x: x.str.replace(current_string, ' '))&lt;/p&gt;

&lt;p&gt;&amp;gt;&amp;gt;&amp;gt; comparison_table = comparison_table.astype(str).apply(&lt;br&gt;
      lambda x: x.str.replace(' +', ' '))&lt;/p&gt;

&lt;p&gt;And — voilà!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ASPBgY_x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/664/1%2As_rHGH1hVZkVrjuuBn9_uA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ASPBgY_x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/664/1%2As_rHGH1hVZkVrjuuBn9_uA.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding a Score Column And Comparing
&lt;/h2&gt;

&lt;p&gt;All that’s left now is to add an empty column named ‘score’ to the DataFrame, calculating the matching scores using our chosen FuzzyWuzzy function,&lt;br&gt;
and populating the DataFrame with those scores.&lt;/p&gt;

&lt;p&gt;Here is an example of how to do that -&lt;/p&gt;

&lt;p&gt;&amp;gt;&amp;gt;&amp;gt; comparison_table["score"] = ""&amp;gt;&amp;gt;&amp;gt; comparison_table['score'] =&lt;br&gt;
comparison_table.apply(lambda row:&lt;br&gt;
fuzz.token_set_ratio(row['col_a_addresses'], row['col_b_addresses']),axis=1)&lt;/p&gt;

&lt;p&gt;Let’s compare the results with those we would have received if we had run the FuzzyWuzzy function on an unprocessed DataFrame:&lt;/p&gt;

&lt;p&gt;Before Cleaning -&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BL6yXE95--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/766/1%2AiJ4Kj3mw_MdoBPOdZMh8Wg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BL6yXE95--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/766/1%2AiJ4Kj3mw_MdoBPOdZMh8Wg.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After Cleaning -&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Hzul-knx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/645/1%2AQg0ZhyBQMpyU9_sTq8G7oA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Hzul-knx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/645/1%2AQg0ZhyBQMpyU9_sTq8G7oA.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, what actually happened after cleaning the data?&lt;br&gt;
The matching scores became more accurate — either increased or decreased based on the cleaning.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;em&gt;Let’s look at row 3 where the score decreased after cleaning.&lt;/em&gt;
In this case — the word “Lane” which appeared on both addresses before cleaning, falsely increased the matching score. But after removing it, we were able to see the addresses are not that similar.&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Let’s look at row 9 where the score increased after cleaning.&lt;/em&gt;
While “Lane” and “ln.” have the same meaning, they are different strings with different capitalization.
Once cleaning the noise out — we were able to receive a much better score, that more accurately reflects the similarity level between those strings.&lt;/li&gt;
&lt;li&gt;  It is also interesting to see that the cleaned strings in row 9 are not identical. ”85" appears only in &lt;em&gt;col_b_addresses&lt;/em&gt; yet the matching score is 100. Why? Since the strings are “close enough” to be determined as a perfect match by the algorithm. A decision that would have likely been the same if a human being had to make it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Choosing a FuzzyWuzzy Function — In a Nutshell
&lt;/h2&gt;

&lt;p&gt;One method to choose the best FuzzyWuzzy function to work with is based on the logic/purpose of the different functions and determining which function seems most relevant for your purposes.&lt;/p&gt;

&lt;p&gt;However, if you cannot decide which function may retrieve the most accurate results — you can conduct a small research to determine what to work with.&lt;/p&gt;

&lt;p&gt;The method I would recommend using would be to take a sample of your data set and run each of the relevant functions against it. Then, for each of the results — manually decide if the value in each row is true positive / false positive / true negative / false negative.&lt;/p&gt;

&lt;p&gt;Once this is done, you can either choose where your TP/FP rate is most satisfactory, or go ahead and calculate accuracy* and sensitivity* as well, and use these values to make your decision.&lt;br&gt;
For each project, our goals may differ, and the false positive / true negative rates we are willing to take will be different.&lt;/p&gt;

&lt;p&gt;* Both accuracy and sensitivity are used in Data-Science and beyond the scope of this article. The formulas for each of these can be found online.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing A Threshold Score — In a Nutshell
&lt;/h2&gt;

&lt;p&gt;My pair of strings returned a matching score of 82. Is it good? Is it bad?&lt;/p&gt;

&lt;p&gt;The answer depends on our target, and there are many relevant questions to ask, such as: are we interested in strings that are very similar to one another, or in different ones? What is the maximal false-positive rate we are willing to accept? What is the minimal true-positive rate we want to work with?&lt;/p&gt;

&lt;p&gt;For the same set of strings, we can come up with two different threshold scores — minimal score for similar strings (for example 85), and maximal score for different strings (for example 72).&lt;br&gt;
There can be a whole range between these threshold scores that will be doomed as “inconclusive”.&lt;/p&gt;

&lt;p&gt;There are different methods to define a threshold score, and we won’t dig into them in this article. I will, however, mention that choosing a threshold score will require some manual work, similar to the one mentioned above regarding how to choose the best FuzzyWuzzy function to work with — taking a sample set of strings with final scores, determining true-positive and false-positive for the results, and eventually deciding where our threshold stands.&lt;/p&gt;

&lt;p&gt;Using FuzzyWuzzy for strings comparison, as well as pre-processing the data, and eventually analyzing the results is a fascinating work. There is always more to do, and different ways to improve the process.&lt;/p&gt;

&lt;p&gt;In this article, we explored some of the practices that make this process useful and comfortable.&lt;/p&gt;

&lt;p&gt;If you enjoyed this article, and/or the previous one, let me know! Share in the comments below a takeaway note for your next project.&lt;/p&gt;

&lt;p&gt;I’d love to hear from you :)&lt;/p&gt;

</description>
      <category>python</category>
      <category>datascience</category>
      <category>preprocessing</category>
      <category>strings</category>
    </item>
    <item>
      <title>Comparing Strings Is Easy With FuzzyWuzzy</title>
      <dc:creator>Naomi Kriger</dc:creator>
      <pubDate>Wed, 13 Jan 2021 12:09:57 +0000</pubDate>
      <link>https://dev.to/behalf/comparing-strings-is-easy-with-fuzzywuzzy-5ck9</link>
      <guid>https://dev.to/behalf/comparing-strings-is-easy-with-fuzzywuzzy-5ck9</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PVm7ekTM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/5184/1%2AAf6NE1u7EXNo8NgGIFN9aw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PVm7ekTM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/5184/1%2AAf6NE1u7EXNo8NgGIFN9aw.jpeg" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;About a year ago, I saw a colleague of mine working on a large data set, aiming to measure the similarity level between each pair of strings. My colleague started to develop a method that calculated the “distance” between the strings, with a set of rules he came up with.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Since I was familiar with the&lt;/em&gt; &lt;a href="https://pypi.org/project/fuzzywuzzy/"&gt;&lt;em&gt;FuzzyWuzzy&lt;/em&gt;&lt;/a&gt; &lt;em&gt;python library, I knew there was a faster and more efficient way to determine if a pair of strings was similar or different. No tedious calculation needed, no reinventing the wheel, just familiarity with FuzzyWuzzy, and with a few other tips that I will share with you today.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is String Comparison, And How Can FuzzyWuzzy Help?
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;FuzzyWuzzy is a Python library that calculates a similarity score for two given strings.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The similarity score is given on a scale of 0 (completely unrelated) to 100 (a close match).&lt;/p&gt;

&lt;p&gt;After all, if all you need is exact string comparison, Python has got you covered:&lt;/p&gt;

&lt;p&gt;&amp;gt;&amp;gt;&amp;gt; "check out this example" == "check out this example"&lt;br&gt;
True&lt;br&gt;
&amp;gt;&amp;gt;&amp;gt; "check out this example" == "something completely different"&lt;br&gt;
False&lt;/p&gt;

&lt;p&gt;But what if your strings are not necessarily &lt;em&gt;exactly&lt;/em&gt; the same, yet you still need to know how similar they are?&lt;/p&gt;

&lt;p&gt;&amp;gt;&amp;gt;&amp;gt; "check out this example" == "check out this exampel"&lt;br&gt;
False&lt;/p&gt;

&lt;p&gt;This isn’t very helpful.&lt;/p&gt;

&lt;p&gt;But check this out:&lt;/p&gt;

&lt;p&gt;&amp;gt;&amp;gt;&amp;gt; fuzz.ratio("check out this example", "check out this exampel")&lt;br&gt;
95&lt;/p&gt;

&lt;p&gt;Much better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;If the relevant libraries are not installed on your virtual environment and imported before usage, you will need to run the followings:&lt;/p&gt;

&lt;p&gt;In a command line:&lt;/p&gt;

&lt;p&gt;pip install pandas&lt;br&gt;
pip install fuzzywuzzy&lt;br&gt;
&lt;strong&gt;&lt;em&gt;# or — preferably&lt;/em&gt;&lt;/strong&gt;pip install fuzzywuzzy[speedup]&lt;br&gt;
&lt;strong&gt;&lt;em&gt;# [speedup] installs python-Levenshtein library&lt;br&gt;
  for better performance&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Inside your IDE:&lt;/p&gt;

&lt;p&gt;&amp;gt;&amp;gt;&amp;gt; import pandas as pd&lt;br&gt;
&amp;gt;&amp;gt;&amp;gt; from fuzzywuzzy import fuzz&lt;/p&gt;

&lt;h2&gt;
  
  
  Levenshtein Distance — Behind the Scenes of FuzzyWuzzy
&lt;/h2&gt;

&lt;p&gt;The different FuzzyWuzzy functions use &lt;a href="https://en.wikipedia.org/wiki/Levenshtein_distance"&gt;Levenshtein distance&lt;/a&gt; — a popular algorithm that calculates the distance between two strings. The “further” those strings are from one another, the greater is the &lt;strong&gt;distance&lt;/strong&gt; score (as &lt;strong&gt;opposed&lt;/strong&gt; to FuzzyWuzzy output).&lt;/p&gt;

&lt;p&gt;However, Levenshtein distance has a major disadvantage:&lt;br&gt;
It has one logic, while in real life there are a few different ways to define similarity of strings.&lt;br&gt;
Levenshtein distance cannot cover different cases with one piece of logic. Some cases would be defined as similar strings by a human being, yet missed by Levenstein.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;&amp;gt;&amp;gt;&amp;gt; Levenshtein.distance(“measuring with Levenshtein”,&lt;br&gt;
                         “measuring differently”)&lt;br&gt;
11&lt;br&gt;
&amp;gt;&amp;gt;&amp;gt; Levenshtein.distance(“Levenshtein distance is here”,&lt;br&gt;
                        “here is distance Levenshtein”)&lt;br&gt;
17&lt;/p&gt;

&lt;p&gt;If someone had to decide which pair of strings is more similar, they would probably pick the second option. However, we can see that it actually got a higher distance score.&lt;/p&gt;

&lt;p&gt;We need something better than that.&lt;/p&gt;

&lt;h1&gt;
  
  
  Getting to Know the Functions
&lt;/h1&gt;

&lt;p&gt;FuzzyWuzzy has a few different functions. Each of these functions takes a pair of strings and returns a 0–100 match score. But each of these functions has a slightly different logic, so we can select the most appropriate function to meet our needs.&lt;/p&gt;

&lt;p&gt;Let’s get to know some prominent FuzzyWuzzy functions:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;fuzz.ratio:&lt;/strong&gt;&lt;br&gt;
    The simplest function. Calculates the score based on the following logic:&lt;br&gt;
    Given two strings, where T is the total number of elements in both sequences, and M is the number of matches, the similarity between those strings is:&lt;br&gt;
    &lt;em&gt;2*(M / T)*100&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&amp;gt;&amp;gt;&amp;gt; fuzz.ratio("great", "green")&lt;br&gt;
60&lt;/p&gt;

&lt;p&gt;In this example -&lt;br&gt;
T = len(“great”)+len(“green”) = 10&lt;br&gt;
M = 3&lt;br&gt;
So the formula is 2*(3/10)*100&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;fuzz.partial_ratio:&lt;/strong&gt;
For two strings, A and B, where len(A) &amp;lt; len(B) and len(A) = n, this function will run ratio function between A and all n-length substrings of B and will retrieve the highest of all scores calculated in this process.
Let’s take a look at the following three examples, and then discuss them:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&amp;gt;&amp;gt;&amp;gt; fuzz.partial_ratio(“let’s compare strings”, “strings”)&lt;br&gt;
100&lt;br&gt;
&amp;gt;&amp;gt;&amp;gt; fuzz.partial_ratio(“let’s compare strings”, “stings”)&lt;br&gt;
83&lt;br&gt;
&amp;gt;&amp;gt;&amp;gt; fuzz.ratio(“let’s compare strings”, “strings”)&lt;br&gt;
50&lt;/p&gt;

&lt;p&gt;The examples above demonstrate the followings:&lt;br&gt;
1. String in B is fully included in string A, therefore the matching score is 100.&lt;br&gt;
2. String in B is almost fully included in string A, except for a “typo”, therefore the matching score is 83.&lt;br&gt;
3. Same as the first example, but using the ratio function between A and B, instead of partial_ratio. Since ratio function is not aimed to handle the substring case — the score is lower.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;fuzz.token_sort_ratio&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sorts the tokens inside both strings (usually split into individual words) and then compares them. This will retrieve a 100 matching score for strings A, B, where A and B contain the same tokens but in different orders.&lt;br&gt;
    See the examples below, once with token_sort_ratio function, and once with ratio function, to see the different results.&lt;/p&gt;

&lt;p&gt;&amp;gt;&amp;gt;&amp;gt; fuzz.token_sort_ratio("let's compare strings",&lt;br&gt;
                              "strings compare let's")&lt;br&gt;
100&lt;br&gt;
&amp;gt;&amp;gt;&amp;gt; fuzz.ratio("let's compare strings", "strings compare let's")&lt;br&gt;
57&lt;/p&gt;

&lt;p&gt;What about the same token but different counts?&lt;/p&gt;

&lt;p&gt;&amp;gt;&amp;gt;&amp;gt; fuzz.token_sort_ratio("let's compare", "let's compare compare")&lt;br&gt;
76&lt;/p&gt;

&lt;p&gt;Well, this isn’t the functions’ specialty. For this case, we have token_set_ratio coming to the rescue.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;fuzz.token_set_ratio&lt;/strong&gt;&lt;br&gt;
The main purpose of token_set_ratio is to ignore duplicates and&lt;br&gt;
order-differences between the given tokens.&lt;/p&gt;

&lt;p&gt;We can see that the two examples below got the same matching score, although in the second example some tokens have been duplicated and their order was changed.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&amp;gt;&amp;gt;&amp;gt; fuzz.token_set_ratio("we compare strings together",&lt;br&gt;
                         "together we talk")&lt;br&gt;
81&lt;br&gt;
&amp;gt;&amp;gt;&amp;gt; fuzz.token_set_ratio("strings we we we compare together", "together together talk we")&lt;br&gt;
81&lt;/p&gt;

&lt;p&gt;The logic behind this function, after &lt;strong&gt;simplifying&lt;/strong&gt; it a bit, is as follows:&lt;br&gt;
Given strings A, B &lt;em&gt;(let’s have A = ‘hi hey ho’ and B = ‘yo yay ho’)&lt;/em&gt;:&lt;br&gt;
C = intersection of A and B &lt;em&gt;(‘ho’)&lt;/em&gt;&lt;br&gt;
D = C + remainder of A &lt;em&gt;(‘ho hi hey’)&lt;/em&gt;&lt;br&gt;
E = C + remainder of B &lt;em&gt;(‘ho yo yay’)&lt;br&gt;
So token_set_ratio&lt;/em&gt; runs ratio(C, D), ratio(C, E), ratio(D, E) and returns the highest score of the three.&lt;/p&gt;

&lt;p&gt;The full logic contains additional normalization, such as applying set() on A and B, applying sort() on C, and more.&lt;/p&gt;

&lt;p&gt;The code implemented by each of the functions described above, as well as other useful FuzzyWuzzy functions, can be found &lt;a href="https://github.com/seatgeek/fuzzywuzzy/blob/master/fuzzywuzzy/fuzz.py"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting To The Nitty Gritty
&lt;/h2&gt;

&lt;p&gt;In this article, we covered the basics of FuzzyWuzzy library and its functions.&lt;/p&gt;

&lt;p&gt;However, getting the best results for our project does not begin and end with knowing which functions are available out there and how to use them.&lt;/p&gt;

&lt;p&gt;Doing it like a pro means knowing how to clean data before working with it, how to compare not only pairs of strings but big tables as well, which threshold score (or scores) to use and so much more.&lt;/p&gt;

&lt;p&gt;To learn all of these, I invite you to read the successive article called &lt;a href="https://dev.to/behalf/fuzzywuzzy-the-before-and-after-46nm"&gt;FuzzyWuzzy — the Before and After&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I would love to hear about your experience with FuzzyWuzzy: when did you use it? For what purposes do you plan using it in the future? What makes working with FuzzyWuzzy fun and comfortable for you?&lt;/p&gt;

&lt;p&gt;Comment below and share your thoughts!&lt;/p&gt;

</description>
      <category>python</category>
      <category>datascience</category>
      <category>data</category>
      <category>strings</category>
    </item>
  </channel>
</rss>
