<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/neat-new-seplyr-feature-string-interpolation/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="http://www.win-vector.com/blog/2017/08/neat-new-seplyr-feature-string-interpolation/"> R – Win-Vector Blog</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>The <a rel="nofollow" href="https://www.r-project.org/" target="_blank"><code>R</code></a> package <a rel="nofollow" href="https://winvector.github.io/seplyr/index.html" target="_blank"><code>seplyr</code></a> has a neat new feature: the function <code>seplyr::expand_expr()</code> which implements what we call “the string algebra” or string expression interpolation. The function takes an expression of mixed terms, including: variables referring to names, quoted strings, and general expression terms. It then “de-quotes” all of the variables referring to quoted strings and “dereferences” variables thought to be referring to names. The entire expression is then returned as a single string.</p>
<p><center><br>
<a rel="nofollow" href="https://winvector.github.io/seplyr/index.html" target="_blank"><img border="0" alt="Safety" title="safety.png" src="https://i2.wp.com/www.win-vector.com/blog/wp-content/uploads/2017/08/safety.png?w=660" data-recalc-dims="1"><br>
</a></center></p>
<p>This provides a powerful way to easily work complicated expressions into the <code>seplyr</code> data manipulation methods.<span></span></p>
<p>The method is easiest to see with an example:</p>
<div>
<pre><code><span>library</span>(<span>&quot;seplyr&quot;</span>)</code></pre>
</div>
<pre><code>## Loading required package: wrapr</code></pre>
<div>
<pre><code>ratio &lt;-<span> </span><span>2</span>
compCol1 &lt;-<span> &quot;Sepal.Width&quot;</span>
expr &lt;-<span> </span><span>expand_expr</span>(<span>&quot;Sepal.Length&quot;</span> >=<span> </span>ratio *<span> </span>compCol1)
<span>print</span>(expr)</code></pre>
</div>
<pre><code>## [1] &quot;Sepal.Length >= ratio * Sepal.Width&quot;</code></pre>
<p><code>expand_expr</code> works by capturing the user supplied expression unevaluated, performing some transformations, and returning the entire expression as a single quoted string (essentially returning new source code).</p>
<p>Notice in the above one layer of quoting was removed from <code>&quot;Sepal.Length&quot;</code> and the name referred to by “<code>compCol1</code>” was substituted into the expression. “<code>ratio</code>” was left alone as it was not referring to a string (and hence can not be a name; unbound or free variables are also left alone). So we see that the substitution performed does depend on what values are present in the environment.</p>
<p>If you want to be stricter in your specification, you could add quotes around any symbol you do not want de-referenced. For example:</p>
<div>
<pre><code><span>expand_expr</span>(<span>&quot;Sepal.Length&quot;</span> >=<span> &quot;ratio&quot;</span> *<span> </span>compCol1)</code></pre>
</div>
<pre><code>## [1] &quot;Sepal.Length >= ratio * Sepal.Width&quot;</code></pre>
<p>After the substitution the returned quoted expression is exactly in the form <code>seplyr</code> expects. For example:</p>
<div>
<pre><code>resCol1 &lt;-<span> &quot;Sepal_Long&quot;</span>

datasets::iris %.>%
<span> </span><span>mutate_se</span>(., 
            resCol1 :<span>=</span><span> </span>expr) %.>%
<span> </span><span>head</span>(.)</code></pre>
</div>
<pre><code>##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species Sepal_Long
## 1          5.1         3.5          1.4         0.2  setosa      FALSE
## 2          4.9         3.0          1.4         0.2  setosa      FALSE
## 3          4.7         3.2          1.3         0.2  setosa      FALSE
## 4          4.6         3.1          1.5         0.2  setosa      FALSE
## 5          5.0         3.6          1.4         0.2  setosa      FALSE
## 6          5.4         3.9          1.7         0.4  setosa      FALSE</code></pre>
<p>Details on <a rel="nofollow" href="https://winvector.github.io/wrapr/reference/grapes-.-greater-than-grapes.html" target="_blank"><code>%.>%</code></a> (dot pipe) and <a rel="nofollow" href="https://winvector.github.io/wrapr/reference/named_map_builder.html" target="_blank"><code>:=</code></a> (named map builder) can be found <a rel="nofollow" href="https://winvector.github.io/wrapr/articles/dot_pipe.html" target="_blank">here</a> and <a rel="nofollow" href="https://winvector.github.io/seplyr/articles/named_map_builder.html" target="_blank">here</a> respectively. The idea is: <code>seplyr::mutate_se(., &quot;Sepal_Long&quot; := &quot;Sepal.Length >= ratio * Sepal.Width&quot;)</code> should be equilant to <code>dplyr::mutate(., Sepal_Long = Sepal.Length >= ratio * Sepal.Width)</code>.</p>
<p><code>seplyr</code> also provides an number of <code>seplyr::*_nse()</code> convenience forms wrapping all of these steps into one operation. For example:</p>
<div>
<pre><code>datasets::iris %.>%
<span> </span><span>mutate_nse</span>(., 
             resCol1 :<span>=</span><span> &quot;Sepal.Length&quot;</span> >=<span> </span>ratio *<span> </span>compCol1) %.>%
<span> </span><span>head</span>(.)</code></pre>
</div>
<pre><code>##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species Sepal_Long
## 1          5.1         3.5          1.4         0.2  setosa      FALSE
## 2          4.9         3.0          1.4         0.2  setosa      FALSE
## 3          4.7         3.2          1.3         0.2  setosa      FALSE
## 4          4.6         3.1          1.5         0.2  setosa      FALSE
## 5          5.0         3.6          1.4         0.2  setosa      FALSE
## 6          5.4         3.9          1.7         0.4  setosa      FALSE</code></pre>
<p>To use string literals you merely need one extra layer of quoting:</p>
<div>
<pre><code><span>&quot;is_setosa&quot;</span> :<span>=</span><span> </span><span>expand_expr</span>(Species ==<span> &quot;'setosa'&quot;</span>)</code></pre>
</div>
<pre><code>##               is_setosa 
## &quot;Species == \&quot;setosa\&quot;&quot;</code></pre>
<div>
<pre><code>datasets::iris %.>%
<span> </span><span>transmute_nse</span>(., 
             <span>&quot;is_setosa&quot;</span> :<span>=</span><span> </span>Species ==<span> &quot;'setosa'&quot;</span>) %.>%
<span> </span><span>summary</span>(.)</code></pre>
</div>
<pre><code>##  is_setosa      
##  Mode :logical  
##  FALSE:100      
##  TRUE :50</code></pre>
<p>The purpose of all of the above is to mix names that are known while we are writing the code (these are quoted) with names that may not be known until later (i.e., column names supplied as parameters). This allows the easy creation of useful generic functions such as:</p>
<div>
<pre><code>countMatches &lt;-<span> </span>function(data, columnName, targetValue) {
  <span># extra quotes to say we are interested in value, not de-reference</span>
  targetSym &lt;-<span> </span><span>paste0</span>(<span>'&quot;'</span>, targetValue, <span>'&quot;'</span>) 
  data %.>%
<span> </span><span>transmute_nse</span>(., <span>&quot;match&quot;</span> :<span>=</span><span> </span>columnName ==<span> </span>targetSym) %.>%
<span> </span><span>group_by_se</span>(., <span>&quot;match&quot;</span>) %.>%
<span> </span><span>summarize_se</span>(., <span>&quot;count&quot;</span> :<span>=</span><span> &quot;n()&quot;</span>)
}

<span>countMatches</span>(datasets::iris, <span>&quot;Species&quot;</span>, <span>&quot;setosa&quot;</span>)</code></pre>
</div>
<pre><code>## # A tibble: 2 x 2
##   match count
##   </code></pre>