<p><div><div><div><div data-width="100" data-show-faces="false" data-send="true" data-layout="button_count" data-height="21" data-href="https://www.r-bloggers.com/fuzzy-string-matching-using-fuzzywuzzyr-and-the-reticulate-package-in-r/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="http://mlampros.github.io/mlampros.github.io/2017/04/13/fuzzywuzzyR_package/"> mlampros</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>I recently released an (other one) R package on CRAN – <strong>fuzzywuzzyR</strong> – which ports the <a target="_blank" rel="nofollow" href="https://github.com/seatgeek/fuzzywuzzy">fuzzywuzzy</a> python library in R. “fuzzywuzzy does fuzzy string matching by using the Levenshtein Distance to calculate the differences between sequences (of character strings).”</p>
<p>There is no <em>big news</em> here as in R already exist similar packages such as the <a target="_blank" rel="nofollow" href="https://github.com/markvanderloo/stringdist">stringdist</a> package. Why then creating the package? Well, I intend to participate in a recently launched <a target="_blank" rel="nofollow" href="https://www.kaggle.com/c/quora-question-pairs">kaggle competition</a> and one popular method to build features (predictors) is fuzzy string matching as explained in this <a target="_blank" rel="nofollow" href="https://www.linkedin.com/pulse/duplicate-quora-question-abhishek-thakur">blog post</a>. My (second) aim was to use the (newly released from Rstudio) <a target="_blank" rel="nofollow" href="https://github.com/rstudio/reticulate">reticulate</a> package, which “provides an R interface to Python modules, classes, and functions” and makes the process of porting python code in R not cumbersome.</p>
<p>First, I’ll explain the functionality of the <strong>fuzzywuzzyR</strong> package and then I’ll give some examples on how to take advantage of the <em>reticulate</em> package in R.</p>
<p></p>
<h4><strong>fuzzywuzzyR</strong></h4>
<p></p>
<p>The <em>fuzzywuzzyR</em> package includes R6-classes / functions for string matching,</p>
<p></p>
<h5><strong>classes</strong></h5>
<p></p>
<table>
<thead>
<tr>
<th>FuzzExtract</th>
<th>FuzzMatcher</th>
<th>FuzzUtils</th>
<th>SequenceMatcher</th>
</tr>
</thead>
<tbody>
<tr>
<td>Extract()</td>
<td>Partial_token_set_ratio()</td>
<td>Full_process()</td>
<td>ratio()</td>
</tr>
<tr>
<td>ExtractBests()</td>
<td>Partial_token_sort_ratio()</td>
<td>Make_type_consistent()</td>
<td>quick_ratio()</td>
</tr>
<tr>
<td>ExtractWithoutOrder()</td>
<td>Ratio()</td>
<td>Asciidammit()</td>
<td>real_quick_ratio()</td>
</tr>
<tr>
<td>ExtractOne()</td>
<td>QRATIO()</td>
<td>Asciionly()</td>
<td>get_matching_blocks()</td>
</tr>
<tr>
<td> </td>
<td>WRATIO()</td>
<td>Validate_string()</td>
<td>get_opcodes()</td>
</tr>
<tr>
<td> </td>
<td>UWRATIO()</td>
<td> </td>
<td> </td>
</tr>
<tr>
<td> </td>
<td>UQRATIO()</td>
<td> </td>
<td> </td>
</tr>
<tr>
<td> </td>
<td>Token_sort_ratio()</td>
<td> </td>
<td> </td>
</tr>
<tr>
<td> </td>
<td>Partial_ratio()</td>
<td> </td>
<td> </td>
</tr>
<tr>
<td> </td>
<td>Token_set_ratio()</td>
<td> </td>
<td> </td>
</tr>
</tbody>
</table>
<p></p>
<h5><strong>functions</strong></h5>
<p></p>
<p>GetCloseMatches()</p>
<p></p>
<p>The following code chunks / examples are part of the package documentation and give an idea on what can be done with the <em>fuzzywuzzyR</em> package,</p>
<p></p>
<h5><em>FuzzExtract</em></h5>
<p></p>
<p>Each one of the methods in the <em>FuzzExtract</em> class takes a <em>character string</em> and a <em>character string sequence</em> as input ( except for the <em>Dedupe</em> method which takes a string sequence only ) and given a <em>processor</em> and a <em>scorer</em> it returns one or more string match(es) and the corresponding score ( in the range 0 – 100 ). Information about the additional parameters (<em>limit</em>, <em>score_cutoff</em> and <em>threshold</em>) can be found in the package documentation,</p>
<p></p>
<div>
<pre><code><span>
</span><span>library</span><span>(</span><span>fuzzywuzzyR</span><span>)</span><span>
</span><span>word</span><span> </span><span>=</span><span> </span><span>&quot;new york jets&quot;</span><span>
</span><span>choices</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>&quot;Atlanta Falcons&quot;</span><span>,</span><span> </span><span>&quot;New York Jets&quot;</span><span>,</span><span> </span><span>&quot;New York Giants&quot;</span><span>,</span><span> </span><span>&quot;Dallas Cowboys&quot;</span><span>)</span><span>
</span><span>#------------
# processor :
#------------
</span><span>
</span><span>init_proc</span><span> </span><span>=</span><span> </span><span>FuzzUtils</span><span>$</span><span>new</span><span>()</span><span> </span><span># initialization of FuzzUtils class to choose a processor
</span><span>
</span><span>PROC</span><span> </span><span>=</span><span> </span><span>init_proc</span><span>$</span><span>Full_process</span><span> </span><span># processor-method
</span><span>
</span><span>PROC1</span><span> </span><span>=</span><span> </span><span>tolower</span><span> </span><span># base R function ( as an example for a processor )
</span><span>
</span><span>#---------
# scorer :
#---------
</span><span>
</span><span>init_scor</span><span> </span><span>=</span><span> </span><span>FuzzMatcher</span><span>$</span><span>new</span><span>()</span><span> </span><span># initialization of the scorer class
</span><span>
</span><span>SCOR</span><span> </span><span>=</span><span> </span><span>init_scor</span><span>$</span><span>WRATIO</span><span> </span><span># choosen scorer function
</span><span>
</span><span>init</span><span> </span><span>&lt;-</span><span> </span><span>FuzzExtract</span><span>$</span><span>new</span><span>()</span><span> </span><span># Initialization of the FuzzExtract class
</span><span>
</span><span>init</span><span>$</span><span>Extract</span><span>(</span><span>string</span><span> </span><span>=</span><span> </span><span>word</span><span>,</span><span> </span><span>sequence_strings</span><span> </span><span>=</span><span> </span><span>choices</span><span>,</span><span> </span><span>processor</span><span> </span><span>=</span><span> </span><span>PROC</span><span>,</span><span> </span><span>scorer</span><span> </span><span>=</span><span> </span><span>SCOR</span><span>)</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span># example output
</span><span> </span><span>[[</span><span>1</span><span>]]</span><span>
</span><span>[[</span><span>1</span><span>]][[</span><span>1</span><span>]]</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>&quot;New York Jets&quot;</span><span>
</span><span>[[</span><span>1</span><span>]][[</span><span>2</span><span>]]</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>100</span><span>
</span><span>[[</span><span>2</span><span>]]</span><span>
</span><span>[[</span><span>2</span><span>]][[</span><span>1</span><span>]]</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>&quot;New York Giants&quot;</span><span>
</span><span>[[</span><span>2</span><span>]][[</span><span>2</span><span>]]</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>79</span><span>
</span><span>[[</span><span>3</span><span>]]</span><span>
</span><span>[[</span><span>3</span><span>]][[</span><span>1</span><span>]]</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>&quot;Atlanta Falcons&quot;</span><span>
</span><span>[[</span><span>3</span><span>]][[</span><span>2</span><span>]]</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>29</span><span>
</span><span>[[</span><span>4</span><span>]]</span><span>
</span><span>[[</span><span>4</span><span>]][[</span><span>1</span><span>]]</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>&quot;Dallas Cowboys&quot;</span><span>
</span><span>[[</span><span>4</span><span>]][[</span><span>2</span><span>]]</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>22</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span># extracts best matches (limited to 2 matches)
</span><span>
</span><span>init</span><span>$</span><span>ExtractBests</span><span>(</span><span>string</span><span> </span><span>=</span><span> </span><span>word</span><span>,</span><span> </span><span>sequence_strings</span><span> </span><span>=</span><span> </span><span>choices</span><span>,</span><span> </span><span>processor</span><span> </span><span>=</span><span> </span><span>PROC1</span><span>,</span><span>
</span><span>scorer</span><span> </span><span>=</span><span> </span><span>SCOR</span><span>,</span><span> </span><span>score_cutoff</span><span> </span><span>=</span><span> </span><span>0L</span><span>,</span><span> </span><span>limit</span><span> </span><span>=</span><span> </span><span>2L</span><span>)</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>[[</span><span>1</span><span>]]</span><span>
</span><span>[[</span><span>1</span><span>]][[</span><span>1</span><span>]]</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>&quot;New York Jets&quot;</span><span>
</span><span>[[</span><span>1</span><span>]][[</span><span>2</span><span>]]</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>100</span><span>
</span><span>[[</span><span>2</span><span>]]</span><span>
</span><span>[[</span><span>2</span><span>]][[</span><span>1</span><span>]]</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>&quot;New York Giants&quot;</span><span>
</span><span>[[</span><span>2</span><span>]][[</span><span>2</span><span>]]</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>79</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span># extracts matches without keeping the output order
</span><span>
</span><span>init</span><span>$</span><span>ExtractWithoutOrder</span><span>(</span><span>string</span><span> </span><span>=</span><span> </span><span>word</span><span>,</span><span> </span><span>sequence_strings</span><span> </span><span>=</span><span> </span><span>choices</span><span>,</span><span> </span><span>processor</span><span> </span><span>=</span><span> </span><span>PROC</span><span>,</span><span>
</span><span>scorer</span><span> </span><span>=</span><span> </span><span>SCOR</span><span>,</span><span> </span><span>score_cutoff</span><span> </span><span>=</span><span> </span><span>0L</span><span>)</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>[[</span><span>1</span><span>]]</span><span>
</span><span>[[</span><span>1</span><span>]][[</span><span>1</span><span>]]</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>&quot;Atlanta Falcons&quot;</span><span>
</span><span>[[</span><span>1</span><span>]][[</span><span>2</span><span>]]</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>29</span><span>
</span><span>[[</span><span>2</span><span>]]</span><span>
</span><span>[[</span><span>2</span><span>]][[</span><span>1</span><span>]]</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>&quot;New York Jets&quot;</span><span>
</span><span>[[</span><span>2</span><span>]][[</span><span>2</span><span>]]</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>100</span><span>
</span><span>[[</span><span>3</span><span>]]</span><span>
</span><span>[[</span><span>3</span><span>]][[</span><span>1</span><span>]]</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>&quot;New York Giants&quot;</span><span>
</span><span>[[</span><span>3</span><span>]][[</span><span>2</span><span>]]</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>79</span><span>
</span><span>[[</span><span>4</span><span>]]</span><span>
</span><span>[[</span><span>4</span><span>]][[</span><span>1</span><span>]]</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>&quot;Dallas Cowboys&quot;</span><span>
</span><span>[[</span><span>4</span><span>]][[</span><span>2</span><span>]]</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>22</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span># extracts first result </span><span>
</span><span>init</span><span>$</span><span>ExtractOne</span><span>(</span><span>string</span><span> </span><span>=</span><span> </span><span>word</span><span>,</span><span> </span><span>sequence_strings</span><span> </span><span>=</span><span> </span><span>choices</span><span>,</span><span> </span><span>processor</span><span> </span><span>=</span><span> </span><span>PROC</span><span>,</span><span>
</span><span>scorer</span><span> </span><span>=</span><span> </span><span>SCOR</span><span>,</span><span> </span><span>score_cutoff</span><span> </span><span>=</span><span> </span><span>0L</span><span>)</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>[[</span><span>1</span><span>]]</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>&quot;New York Jets&quot;</span><span>
</span><span>[[</span><span>2</span><span>]]</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>100</span><span>
</span></code></pre>
</div>
<p></p>
<p>The <em>dedupe</em> method removes duplicates from a sequence of character strings using fuzzy string matching,</p>
<p></p>
<div>
<pre><code><span>
</span><span>duplicat</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>'Frodo Baggins'</span><span>,</span><span> </span><span>'Tom Sawyer'</span><span>,</span><span> </span><span>'Bilbo Baggin'</span><span>,</span><span> </span><span>'Samuel L. Jackson'</span><span>,</span><span>
</span><span>'F. Baggins'</span><span>,</span><span> </span><span>'Frody Baggins'</span><span>,</span><span> </span><span>'Bilbo Baggins'</span><span>)</span><span>
</span><span>init</span><span>$</span><span>Dedupe</span><span>(</span><span>contains_dupes</span><span> </span><span>=</span><span> </span><span>duplicat</span><span>,</span><span> </span><span>threshold</span><span> </span><span>=</span><span> </span><span>70L</span><span>,</span><span> </span><span>scorer</span><span> </span><span>=</span><span> </span><span>SCOR</span><span>)</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>&quot;Frodo Baggins&quot;</span><span> </span><span>&quot;Samuel L. Jackson&quot;</span><span> </span><span>&quot;Bilbo Baggins&quot;</span><span> </span><span>&quot;Tom Sawyer&quot;</span><span>
</span></code></pre>
</div>
<p></p>
<h5><em>FuzzMatcher</em></h5>
<p></p>
<p>Each one of the methods in the <em>FuzzMatcher</em> class takes two <em>character strings</em> (string1, string2) as input and returns a score ( in range 0 to 100 ). Information about the additional parameters (<em>force_ascii</em>, <em>full_process</em> and <em>threshold</em>) can be found in the package documentation,</p>
<div>
<pre><code><span>
</span><span>s</span><span>1</span><span> </span><span>=</span><span> </span><span>&quot;Atlanta Falcons&quot;</span><span>
</span><span>s</span><span>2</span><span> </span><span>=</span><span> </span><span>&quot;New York Jets&quot;</span><span>
</span><span>init</span><span> </span><span>=</span><span> </span><span>FuzzMatcher</span><span>$</span><span>new</span><span>()</span><span> </span><span>initialization</span><span> </span><span>of</span><span> </span><span>FuzzMatcher</span><span> </span><span>class</span><span>
</span><span>init</span><span>$</span><span>Partial_token_set_ratio</span><span>(</span><span>string1</span><span> </span><span>=</span><span> </span><span>s</span><span>1</span><span>,</span><span> </span><span>string2</span><span> </span><span>=</span><span> </span><span>s</span><span>2</span><span>,</span><span> </span><span>force_ascii</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>,</span><span> </span><span>full_process</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>)</span><span>
</span><span># example output
</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>31</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>init</span><span>$</span><span>Partial_token_sort_ratio</span><span>(</span><span>string1</span><span> </span><span>=</span><span> </span><span>s</span><span>1</span><span>,</span><span> </span><span>string2</span><span> </span><span>=</span><span> </span><span>s</span><span>2</span><span>,</span><span> </span><span>force_ascii</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>,</span><span> </span><span>full_process</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>)</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>31</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>init</span><span>$</span><span>Ratio</span><span>(</span><span>string1</span><span> </span><span>=</span><span> </span><span>s</span><span>1</span><span>,</span><span> </span><span>string2</span><span> </span><span>=</span><span> </span><span>s</span><span>2</span><span>)</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>21</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>init</span><span>$</span><span>QRATIO</span><span>(</span><span>string1</span><span> </span><span>=</span><span> </span><span>s</span><span>1</span><span>,</span><span> </span><span>string2</span><span> </span><span>=</span><span> </span><span>s</span><span>2</span><span>,</span><span> </span><span>force_ascii</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>)</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>29</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>init</span><span>$</span><span>WRATIO</span><span>(</span><span>string1</span><span> </span><span>=</span><span> </span><span>s</span><span>1</span><span>,</span><span> </span><span>string2</span><span> </span><span>=</span><span> </span><span>s</span><span>2</span><span>,</span><span> </span><span>force_ascii</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>)</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>29</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>init</span><span>$</span><span>UWRATIO</span><span>(</span><span>string1</span><span> </span><span>=</span><span> </span><span>s</span><span>1</span><span>,</span><span> </span><span>string2</span><span> </span><span>=</span><span> </span><span>s</span><span>2</span><span>)</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>29</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>init</span><span>$</span><span>UQRATIO</span><span>(</span><span>string1</span><span> </span><span>=</span><span> </span><span>s</span><span>1</span><span>,</span><span> </span><span>string2</span><span> </span><span>=</span><span> </span><span>s</span><span>2</span><span>)</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>29</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>init</span><span>$</span><span>Token_sort_ratio</span><span>(</span><span>string1</span><span> </span><span>=</span><span> </span><span>s</span><span>1</span><span>,</span><span> </span><span>string2</span><span> </span><span>=</span><span> </span><span>s</span><span>2</span><span>,</span><span> </span><span>force_ascii</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>,</span><span> </span><span>full_process</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>)</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>29</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>init</span><span>$</span><span>Partial_ratio</span><span>(</span><span>string1</span><span> </span><span>=</span><span> </span><span>s</span><span>1</span><span>,</span><span> </span><span>string2</span><span> </span><span>=</span><span> </span><span>s</span><span>2</span><span>)</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>23</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>init</span><span>$</span><span>Token_set_ratio</span><span>(</span><span>string1</span><span> </span><span>=</span><span> </span><span>s</span><span>1</span><span>,</span><span> </span><span>string2</span><span> </span><span>=</span><span> </span><span>s</span><span>2</span><span>,</span><span> </span><span>force_ascii</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>,</span><span> </span><span>full_process</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>)</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>29</span><span>
</span></code></pre>
</div>
<p></p>
<h5><em>FuzzUtils</em></h5>
<p></p>
<p>The <em>FuzzUtils</em> class includes a number of utility methods, from which the <em>Full_process</em> method is from greater importance as besides its main functionality it can also be used as a secondary function in some of the other fuzzy matching classes,</p>
<p></p>
<div>
<pre><code><span>
</span><span>s</span><span>1</span><span> </span><span>=</span><span> </span><span>'Frodo Baggins'</span><span>
</span><span>init</span><span> </span><span>=</span><span> </span><span>FuzzUtils</span><span>$</span><span>new</span><span>()</span><span>
</span><span>init</span><span>$</span><span>Full_process</span><span>(</span><span>string</span><span> </span><span>=</span><span> </span><span>s</span><span>1</span><span>,</span><span> </span><span>force_ascii</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>)</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span># example output
</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>&quot;frodo baggins&quot;</span><span>
</span></code></pre>
</div>
<p></p>
<h5><em>GetCloseMatches</em></h5>
<p></p>
<p>The <em>GetCloseMatches</em> method returns a list of the best “good enough” matches. The parameter <em>string</em> is a sequence for which close matches are desired (typically a character string), and <em>sequence_strings</em> is a list of sequences against which to match the parameter <em>string</em> (typically a list of strings).</p>
<p></p>
<div>
<pre><code><span>
</span><span>vec</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>'Frodo Baggins'</span><span>,</span><span> </span><span>'Tom Sawyer'</span><span>,</span><span> </span><span>'Bilbo Baggin'</span><span>)</span><span>
</span><span>str1</span><span> </span><span>=</span><span> </span><span>'Fra Bagg'</span><span>
</span><span>GetCloseMatches</span><span>(</span><span>string</span><span> </span><span>=</span><span> </span><span>str1</span><span>,</span><span> </span><span>sequence_strings</span><span> </span><span>=</span><span> </span><span>vec</span><span>,</span><span> </span><span>n</span><span> </span><span>=</span><span> </span><span>2L</span><span>,</span><span> </span><span>cutoff</span><span> </span><span>=</span><span> </span><span>0.6</span><span>)</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>&quot;Frodo Baggins&quot;</span><span>
</span></code></pre>
</div>
<p></p>
<h5><em>SequenceMatcher</em></h5>
<p></p>
<p>The <em>SequenceMatcher</em> class is based on <a target="_blank" rel="nofollow" href="https://www.npmjs.com/package/difflib">difflib</a> which comes by default installed with python and includes the following fuzzy string matching methods,</p>
<p></p>
<div>
<pre><code><span>
</span><span>s</span><span>1</span><span> </span><span>=</span><span> </span><span>' It was a dark and stormy night. I was all alone sitting on a red chair.'</span><span>
</span><span>s</span><span>2</span><span> </span><span>=</span><span> </span><span>' It was a murky and stormy night. I was all alone sitting on a crimson chair.'</span><span>
</span><span>init</span><span> </span><span>=</span><span> </span><span>SequenceMatcher</span><span>$</span><span>new</span><span>(</span><span>string1</span><span> </span><span>=</span><span> </span><span>s</span><span>1</span><span>,</span><span> </span><span>string2</span><span> </span><span>=</span><span> </span><span>s</span><span>2</span><span>)</span><span>
</span><span>init</span><span>$</span><span>ratio</span><span>()</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>0.9127517</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>init</span><span>$</span><span>quick_ratio</span><span>()</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>0.9127517</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>init</span><span>$</span><span>real_quick_ratio</span><span>()</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>0.966443</span><span> </span></code></pre>
</div>
<p></p>
<p>The <em>get_matching_blocks</em> and <em>get_opcodes</em> return triples and 5-tuples describing matching subsequences. More information can be found in the <a target="_blank" rel="nofollow" href="https://www.npmjs.com/package/difflib">Python’s difflib module</a> and in the <em>fuzzywuzzyR</em> package documentation.</p>
<p></p>
<p>A last think to note here is that the mentioned fuzzy string matching classes can be parallelized using the base R <em>parallel</em> package. For instance, the following <em>MCLAPPLY_RATIOS</em> function can take two vectors of character strings (QUERY1, QUERY2) and return the scores for each method of the <em>FuzzMatcher</em> class,</p>
<p></p>
<div>
<pre><code><span>
</span><span>MCLAPPLY_RATIOS</span><span> </span><span>=</span><span> </span><span>function</span><span>(</span><span>QUERY1</span><span>,</span><span> </span><span>QUERY2</span><span>,</span><span> </span><span>class_fuzz</span><span> </span><span>=</span><span> </span><span>'FuzzMatcher'</span><span>,</span><span> </span><span>method_fuzz</span><span> </span><span>=</span><span> </span><span>'QRATIO'</span><span>,</span><span> </span><span>threads</span><span> </span><span>=</span><span> </span><span>1</span><span>,</span><span> </span><span>...</span><span>)</span><span> </span><span>{</span><span>
</span><span>init</span><span> </span><span>&lt;-</span><span> </span><span>eval</span><span>(</span><span>parse</span><span>(</span><span>text</span><span> </span><span>=</span><span> </span><span>paste0</span><span>(</span><span>class_fuzz</span><span>,</span><span> </span><span>'$new()'</span><span>)))</span><span>
</span><span>METHOD</span><span> </span><span>=</span><span> </span><span>paste0</span><span>(</span><span>'init$'</span><span>,</span><span> </span><span>method_fuzz</span><span>)</span><span>
</span><span>if</span><span> </span><span>(</span><span>threads</span><span> </span><span>==</span><span> </span><span>1</span><span>)</span><span> </span><span>{</span><span>
</span><span>res_qrat</span><span> </span><span>=</span><span> </span><span>lapply</span><span>(</span><span>1</span><span>:</span><span>length</span><span>(</span><span>QUERY1</span><span>),</span><span> </span><span>function</span><span>(</span><span>x</span><span>)</span><span> </span><span>do.call</span><span>(</span><span>eval</span><span>(</span><span>parse</span><span>(</span><span>text</span><span> </span><span>=</span><span> </span><span>METHOD</span><span>)),</span><span> </span><span>list</span><span>(</span><span>QUERY1</span><span>[[</span><span>x</span><span>]],</span><span> </span><span>QUERY2</span><span>[[</span><span>x</span><span>]],</span><span> </span><span>...</span><span>)))}</span><span>
</span><span>else</span><span> </span><span>{</span><span>
</span><span>res_qrat</span><span> </span><span>=</span><span> </span><span>parallel</span><span>::</span><span>mclapply</span><span>(</span><span>1</span><span>:</span><span>length</span><span>(</span><span>QUERY1</span><span>),</span><span> </span><span>function</span><span>(</span><span>x</span><span>)</span><span> </span><span>do.call</span><span>(</span><span>eval</span><span>(</span><span>parse</span><span>(</span><span>text</span><span> </span><span>=</span><span> </span><span>METHOD</span><span>)),</span><span> </span><span>list</span><span>(</span><span>QUERY1</span><span>[[</span><span>x</span><span>]],</span><span> </span><span>QUERY2</span><span>[[</span><span>x</span><span>]],</span><span> </span><span>...</span><span>)),</span><span> </span><span>mc.cores</span><span> </span><span>=</span><span> </span><span>threads</span><span>)</span><span>
</span><span>}</span><span>
</span><span>return</span><span>(</span><span>res_qrat</span><span>)</span><span>
</span><span>}</span><span>
</span></code></pre>
</div>
<p></p>
<div>
<pre><code><span>
</span><span>query1</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>'word1'</span><span>,</span><span> </span><span>'word2'</span><span>,</span><span> </span><span>'word3'</span><span>)</span><span>
</span><span>query2</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>'similarword1'</span><span>,</span><span> </span><span>'similar_word2'</span><span>,</span><span> </span><span>'similarwor'</span><span>)</span><span>
</span><span>quer_res</span><span> </span><span>=</span><span> </span><span>MCLAPPLY_RATIOS</span><span>(</span><span>query1</span><span>,</span><span> </span><span>query2</span><span>,</span><span> </span><span>class_fuzz</span><span> </span><span>=</span><span> </span><span>'FuzzMatcher'</span><span>,</span><span> </span><span>method_fuzz</span><span> </span><span>=</span><span> </span><span>'QRATIO'</span><span>,</span><span> </span><span>threads</span><span> </span><span>=</span><span> </span><span>1</span><span>)</span><span>
</span><span>unlist</span><span>(</span><span>quer_res</span><span>)</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span># example output
</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>59</span><span> </span><span>56</span><span> </span><span>40</span><span>
</span></code></pre>
</div>
<h3><strong>reticulate</strong> package</h3>
<p></p>
<p>My personal opinion is that the newly released <a target="_blank" rel="nofollow" href="https://github.com/rstudio/reticulate">reticulate</a> package is <em>good news</em> (for all R-users with minimal knowledge of python) and <em>bad news</em> (for package maintainers whose packages do not cover the full spectrum of a subject in comparison to an existing python library) at the same time. I’ll explain this in the following two examples.</p>
<p></p>
<p>As an R user I’d always like to have a <em>truncated svd</em> function similar to the one of the <a target="_blank" rel="nofollow" href="http://scikit-learn.org/stable/modules/generated/sklearn.decomposition.TruncatedSVD.html">sklearn</a> python library. So, now in R using the reticulate package and the <a target="_blank" rel="nofollow" href="https://github.com/mlampros/DataSets">mnist data</a> set one can do,</p>
<p></p>
<div>
<pre><code><span>
</span><span>reticulate</span><span>::</span><span>py_module_available</span><span>(</span><span>'sklearn'</span><span>)</span><span> </span><span># check that 'sklearn' is available in your OS
</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>TRUE</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>dim</span><span>(</span><span>mnist</span><span>)</span><span> </span><span># after downloading and opening the data from the previous link
</span><span>
</span><span>70000</span><span> </span><span>785</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>mnist</span><span> </span><span>=</span><span> </span><span>as.matrix</span><span>(</span><span>mnist</span><span>)</span><span> </span><span># convert to matrix
</span><span>
</span><span>trunc_SVD</span><span> </span><span>=</span><span> </span><span>reticulate</span><span>::</span><span>import</span><span>(</span><span>'sklearn.decomposition'</span><span>)</span><span>
</span><span>res_svd</span><span> </span><span>=</span><span> </span><span>trunc_SVD</span><span>$</span><span>TruncatedSVD</span><span>(</span><span>n_components</span><span> </span><span>=</span><span> </span><span>100L</span><span>,</span><span> </span><span>n_iter</span><span> </span><span>=</span><span> </span><span>5L</span><span>,</span><span> </span><span>random_state</span><span> </span><span>=</span><span> </span><span>1L</span><span>)</span><span>
</span><span>res_svd</span><span>$</span><span>fit</span><span>(</span><span>mnist</span><span>)</span><span>
</span><span># TruncatedSVD(algorithm='randomized', n_components=100, n_iter=5,
# random_state=1, tol=0.0)
</span><span> </span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>out_svd</span><span> </span><span>=</span><span> </span><span>res_svd</span><span>$</span><span>transform</span><span>(</span><span>mnist</span><span>)</span><span>
</span><span>str</span><span>(</span><span>out_svd</span><span>)</span><span>
</span><span># num [1:70000, 1:100] 1752 1908 2289 2237 2236 ...
</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>class</span><span>(</span><span>out_svd</span><span>)</span><span>
</span><span># [1] &quot;matrix&quot;
</span><span>
</span></code></pre>
</div>
<p></p>
<p>to receive the desired output ( a matrix with 70000 rows and 100 columns (components) ).</p>
<p></p>
<p>As a package maintainer, I do receive from time to time e-mails from users of my packages. In one of them a user asked me if the hog function of the <a target="_blank" rel="nofollow" href="https://github.com/mlampros/OpenImageR">OpenImageR</a> package is capable of plotting the hog features. Actually not, but now an R-user can, for instance, use the <a target="_blank" rel="nofollow" href="http://scikit-image.org/">scikit-image</a> python library to <a target="_blank" rel="nofollow" href="http://scikit-image.org/docs/dev/auto_examples/features_detection/plot_hog.html">plot the hog-features</a> using the following code chunk,</p>
<p></p>
<div>
<pre><code><span>
</span><span>reticulate</span><span>::</span><span>py_module_available</span><span>(</span><span>&quot;skimage&quot;</span><span>)</span><span> </span><span># check that 'sklearn' is available in your OS
</span><span>
</span><span># [1] TRUE
</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>feat</span><span> </span><span>&lt;-</span><span> </span><span>reticulate</span><span>::</span><span>import</span><span>(</span><span>&quot;skimage.feature&quot;</span><span>)</span><span> </span><span># import module
</span><span>
</span><span>data_sk</span><span> </span><span>&lt;-</span><span> </span><span>reticulate</span><span>::</span><span>import</span><span>(</span><span>&quot;skimage.data&quot;</span><span>)</span><span> </span><span># import data
</span><span>
</span><span>color</span><span> </span><span>&lt;-</span><span> </span><span>reticulate</span><span>::</span><span>import</span><span>(</span><span>&quot;skimage.color&quot;</span><span>)</span><span> </span><span># import module to plot </span><span>
</span><span>tmp_im</span><span> </span><span>=</span><span> </span><span>data_sk</span><span>$</span><span>astronaut</span><span>()</span><span> </span><span># import specific image data ('astronaut')
</span><span>
</span><span>dim</span><span>(</span><span>tmp_im</span><span>)</span><span>
</span><span># [1] 512 512 3
</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>image</span><span> </span><span>=</span><span> </span><span>color</span><span>$</span><span>rgb2gray</span><span>(</span><span>tmp_im</span><span>)</span><span> </span><span># convert to gray
</span><span>
</span><span>dim</span><span>(</span><span>image</span><span>)</span><span>
</span><span># [1] 512 512
</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>res</span><span> </span><span>=</span><span> </span><span>feat</span><span>$</span><span>hog</span><span>(</span><span>image</span><span>,</span><span> </span><span>orientations</span><span> </span><span>=</span><span> </span><span>8L</span><span>,</span><span> </span><span>pixels_per_cell</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>16L</span><span>,</span><span> </span><span>16L</span><span>),</span><span> </span><span>cells_per_block</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>1L</span><span>,</span><span> </span><span>1L</span><span>),</span><span> </span><span>visualise</span><span>=</span><span>T</span><span>)</span><span>
</span><span>str</span><span>(</span><span>res</span><span>)</span><span>
</span><span># List of 2
# $ : num [1:8192(1d)] 1.34e-04 1.53e-04 6.68e-05 9.19e-05 7.93e-05 ...
# $ : num [1:512, 1:512] 0 0 0 0 0 0 0 0 0 0 ...
</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>OpenImageR</span><span>::</span><span>imageShow</span><span>(</span><span>res</span><span>[[</span><span>2</span><span>]])</span><span> </span><span># using the OpenImageR to plot the data
</span><span>
</span></code></pre>
</div>
<p><img alt="Alt text" src="https://i0.wp.com/mlampros.github.io/images/hog_plot_astronaut.png?w=456" data-recalc-dims="1"></p>
<p></p>
<p>As a final word, I think that the <em>reticulate</em> package, although not that popular yet, it will make a difference in the R-community.</p>
<p></p>
<p>The <em>README.md</em> file of the <em>fuzzywuzzyR</em> package includes the SystemRequirements and detailed installation instructions for each OS.</p>
<p>An updated version of the fuzzywuzzyR package can be found in my <a target="_blank" rel="nofollow" href="https://github.com/mlampros/fuzzywuzzyR">Github repository</a> and to report bugs/issues please use the following link, <a target="_blank" rel="nofollow" href="https://github.com/mlampros/fuzzywuzzyR/issues">https://github.com/mlampros/fuzzywuzzyR/issues</a>.</p>
<p></p>
<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="http://mlampros.github.io/mlampros.github.io/2017/04/13/fuzzywuzzyR_package/"> mlampros</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a title="The R Project for Statistical Computing" rel="nofollow" href="https://www.r-project.org/">R</a> news and <a title="R tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/tutorial">tutorials</a> on topics such as: <a title="Data science" rel="nofollow" href="https://www.r-bloggers.com/search/data%20science">Data science</a>, <a title="Big Data" rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data">Big Data, <a title="R jobs" rel="nofollow" href="https://www.r-users.com/">R jobs</a>, visualization (<a title="ggplot and ggplot2 tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2">ggplot2</a>, <a title="Boxplots using lattice and ggplot2 tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/boxplot">Boxplots</a>, <a title="Maps and gis" rel="nofollow" href="https://www.r-bloggers.com/search/map">maps</a>, <a title="Animation in R" rel="nofollow" href="https://www.r-bloggers.com/search/animation">animation</a>), programming (<a title="RStudio IDE for R" rel="nofollow" href="https://www.r-bloggers.com/search/RStudio">RStudio</a>, <a title="Sweave and literate programming" rel="nofollow" href="https://www.r-bloggers.com/search/sweave">Sweave</a>, <a title="LaTeX in R" rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX">LaTeX</a>, <a title="SQL and databases" rel="nofollow" href="https://www.r-bloggers.com/search/SQL">SQL</a>, <a title="Eclipse IDE for R" rel="nofollow" href="https://www.r-bloggers.com/search/eclipse">Eclipse</a>, <a title="git and github, Version Control System" rel="nofollow" href="https://www.r-bloggers.com/search/git">git</a>, <a title="Large data in R using Hadoop" rel="nofollow" href="https://www.r-bloggers.com/search/hadoop">hadoop</a>, <a title="Web Scraping of google, facebook, yahoo, twitter and more using R" rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping">Web Scraping</a>) statistics (<a title="Regressions and ANOVA analysis tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/regression">regression</a>, <a title="principal component analysis tutorial" rel="nofollow" href="https://www.r-bloggers.com/search/PCA">PCA</a>, <a title="Time series" rel="nofollow" href="https://www.r-bloggers.com/search/time+series">time series</a>, <a title="finance trading" rel="nofollow" href="https://www.r-bloggers.com/search/trading">trading</a>) and more...
<img height="1" alt="" width="1" src="http://feeds.feedburner.com/~r/RBloggers/~4/S1_GcKBJnno"></a></div>