<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Random R Ramblings</title>
    <link>/</link>
    <description>Recent content on Random R Ramblings</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-gb</language>
    <lastBuildDate>Mon, 29 Mar 2021 20:12:00 -0500</lastBuildDate>
    
        <atom:link href="/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>{poorman}: Version 0.2.5 Release</title>
      <link>/2021/03/29/poorman-version-0.2.5-release/</link>
      <pubDate>Mon, 29 Mar 2021 20:12:00 -0500</pubDate>
      
      <guid>/2021/03/29/poorman-version-0.2.5-release/</guid>
      <description>
&lt;script src=&#34;/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;poorman-0.2.5&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;{poorman} 0.2.5&lt;/h1&gt;
&lt;p&gt;Yesterday I released the ninth version of &lt;a href=&#34;https://github.com/nathaneastwood/poorman&#34;&gt;{poorman}&lt;/a&gt; to CRAN.&lt;/p&gt;
&lt;p&gt;This update has added the following new features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;summarise()&lt;/code&gt; can now revise grouping structures with the &lt;code&gt;.groups&lt;/code&gt; argument (&lt;a href=&#34;https://github.com/nathaneastwood/poorman/issues/82&#34;&gt;#57&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;group_by()&lt;/code&gt; can now drop groups formed by factor levels that don’t appear in the data with the &lt;code&gt;.drop&lt;/code&gt; parameter (&lt;a href=&#34;https://github.com/nathaneastwood/poorman/issues/63&#34;&gt;#63&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;New cumulative functions have been added: &lt;code&gt;cumall()&lt;/code&gt;, &lt;code&gt;cumany()&lt;/code&gt; and &lt;code&gt;cummean()&lt;/code&gt; (&lt;a href=&#34;https://github.com/nathaneastwood/poorman/issues/64&#34;&gt;#64&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Additional tools for working with rownames have been added: &lt;code&gt;has_rownames()&lt;/code&gt;, &lt;code&gt;remove_rownames()&lt;/code&gt;, &lt;code&gt;column_to_rownames()&lt;/code&gt;, &lt;code&gt;rowid_to_column()&lt;/code&gt; (&lt;a href=&#34;https://github.com/nathaneastwood/poorman/issues/66&#34;&gt;#66&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;filter()&lt;/code&gt; gains the &lt;code&gt;.preserve&lt;/code&gt; parameters (&lt;a href=&#34;https://github.com/nathaneastwood/poorman/issues/81&#34;&gt;#81&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;if_any()&lt;/code&gt; and &lt;code&gt;if_all()&lt;/code&gt; were added (#80).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following fixes were also implemented:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;mutate()&lt;/code&gt; now successfully evaluates functions defined in the scope of a parent function (&lt;a href=&#34;https://github.com/nathaneastwood/poorman/issues/68&#34;&gt;#68&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;select_positions()&lt;/code&gt; now works if passed a combination of positive and negative values (&lt;a href=&#34;https://github.com/nathaneastwood/poorman/issues/71&#34;&gt;#71&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transmute()&lt;/code&gt; now keeps unnamed columns that it creates (&lt;a href=&#34;https://github.com/nathaneastwood/poorman/issues/72&#34;&gt;#72&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following refactorisations took place:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When grouping data with &lt;code&gt;group_by()&lt;/code&gt;, it will now create an object of class &lt;code&gt;grouped_df&lt;/code&gt; and not &lt;code&gt;grouped_data&lt;/code&gt; which keeps it consistent with the {dplyr} method name (&lt;a href=&#34;https://github.com/nathaneastwood/poorman/issues/70&#34;&gt;#70&lt;/a&gt;). This should hopefully make transitioning packages from {dplyr} to {poorman} a little easier.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Filling NA Values Using the Last Observation Carried Forward with {dplyr}, {dbplyr} and {sparklyr}</title>
      <link>/2021/03/21/filling-na-values-using-the-last-observation-carried-forward-with-dplyr-dbplyr-and-sparklyr/</link>
      <pubDate>Sun, 21 Mar 2021 20:12:00 -0500</pubDate>
      
      <guid>/2021/03/21/filling-na-values-using-the-last-observation-carried-forward-with-dplyr-dbplyr-and-sparklyr/</guid>
      <description>
&lt;script src=&#34;/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;the-problem&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;The Problem&lt;/h1&gt;
&lt;p&gt;Real life data is often riddled with missing values - or &lt;code&gt;NA&lt;/code&gt;s - where no data value are stored for the variable in observation. Missing data such as this can have a significant effect on the conclusions which can be drawn from the data. For example individuals dropping out of a study or subjects not properly reporting responses. A common solution to this problem is to fill those &lt;code&gt;NA&lt;/code&gt; values with the most recent non-&lt;code&gt;NA&lt;/code&gt; value prior to it - this is called the Last Observation Carried Forward (LOCF) method.&lt;/p&gt;
&lt;p&gt;This blog post will look at how to implement this particular solution using a combination of {dplyr}, {dbplyr} and {sparklyr}.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;solving-the-problem-with-dbplyr&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Solving the Problem with {dbplyr}&lt;/h1&gt;
&lt;p&gt;For this problem we will be using the following temperature data.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# # Source: spark&amp;lt;temperature&amp;gt; [?? x 3]
#     year month  temp
#    &amp;lt;int&amp;gt; &amp;lt;int&amp;gt; &amp;lt;dbl&amp;gt;
#  1  2016     1   6.9
#  2  2016     2  NA  
#  3  2016     3  10.1
#  4  2016     4  11.5
#  5  2016     5  16.3
#  6  2016     6  19.1
#  7  2016     7  NA  
#  8  2016     8  NA  
#  9  2016     9  17.6
# 10  2016    10  13.6
# # … with more rows&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It might be reasonable to assume that we can fill the &lt;code&gt;NA&lt;/code&gt; values of the &lt;code&gt;temp&lt;/code&gt; column with the previous month’s data.&lt;/p&gt;
&lt;p&gt;The strategy to forward fill in Spark is to use what’s known as a &lt;a href=&#34;https://www.postgresql.org/docs/9.1/tutorial-window.html&#34;&gt;window function&lt;/a&gt;. A window function performs a calculation across a set of table rows that are somehow related to the current row. This is comparable to the type of calculation that can be done with an aggregate function. But unlike regular aggregate functions, use of a window function does not cause rows to become grouped into a single output row — the rows retain their separate identities. Behind the scenes, the window function is able to access more than just the current row of the query result.&lt;/p&gt;
&lt;p&gt;We can perform window functions in Spark using &lt;code&gt;dbplyr::win_over()&lt;/code&gt;. In this function we define the window &lt;code&gt;frame&lt;/code&gt; which - for the LOCF method - includes all rows from the beginning of time up to the current row, i.e. &lt;code&gt;-Inf&lt;/code&gt; to &lt;code&gt;0&lt;/code&gt;. We need to specify that our data follow a particular &lt;code&gt;order&lt;/code&gt; which is the &lt;code&gt;month&lt;/code&gt; in ascending order. We also need to partition the data by the &lt;code&gt;year&lt;/code&gt; which can be thought of as acting like &lt;code&gt;dplyr::group_by()&lt;/code&gt;. Finally we define the expression to perform on the data which, since we need the last non-&lt;code&gt;NA&lt;/code&gt; value, can be obtained using the Spark SQL function &lt;code&gt;last()&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;last(expr[, isIgnoreNull])&lt;/code&gt; - Returns the last value of expr for a group of rows. If &lt;code&gt;isIgnoreNull&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt;, returns only non-null values.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Putting this all together, we have the following operation.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;temperature &amp;lt;- dplyr::mutate(
  .data = temperature,
  tempLOCF = dbplyr::win_over(
    expr = dplyr::sql(&amp;quot;last(temp, true)&amp;quot;),
    partition = &amp;quot;year&amp;quot;,
    order = &amp;quot;month&amp;quot;,
    frame = c(-Inf, 0),
    con = sc
  )
)
temperature
# # Source: spark&amp;lt;?&amp;gt; [?? x 4]
#     year month  temp tempLOCF
#    &amp;lt;int&amp;gt; &amp;lt;int&amp;gt; &amp;lt;dbl&amp;gt;    &amp;lt;dbl&amp;gt;
#  1  2016     1   6.9      6.9
#  2  2016     2  NA        6.9
#  3  2016     3  10.1     10.1
#  4  2016     4  11.5     11.5
#  5  2016     5  16.3     16.3
#  6  2016     6  19.1     19.1
#  7  2016     7  NA       19.1
#  8  2016     8  NA       19.1
#  9  2016     9  17.6     17.6
# 10  2016    10  13.6     13.6
# # … with more rows&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So now we can see that we have filled the values as expected. The way this works is that {dbplyr} takes our regular {dplyr} code and translates it to SQL code. We can see the SQL that {dbplyr} generates for us with &lt;code&gt;dbplyr::sql_render()&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;dbplyr::sql_render(query = temperature)
# &amp;lt;SQL&amp;gt; SELECT `year`, `month`, `temp`, last(temp, true) OVER (PARTITION BY `year` ORDER BY `month` ROWS UNBOUNDED PRECEDING) AS `tempLOCF`
# FROM `temperature`&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that the &lt;code&gt;con = sc&lt;/code&gt; here is required such that {dbplyr} can set up the SQL for the particular database engine you are working with - in this case, Spark.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;bonus---next-observation-carried-backwards&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Bonus - Next Observation Carried Backwards&lt;/h1&gt;
&lt;p&gt;The Next Observation Carried Backwards method is very similar to LOCF except, you guessed it, we carry the next non-&lt;code&gt;NA&lt;/code&gt; value backwards. This can be achieved with the exact same code expect the &lt;code&gt;frame&lt;/code&gt; changes to be from the current row to the end of the partition (or group) and we take the &lt;code&gt;first()&lt;/code&gt; non-&lt;code&gt;NA&lt;/code&gt; value from the window frame.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;dplyr::mutate(
  .data = temperature,
  tempNOCB = dbplyr::win_over(
    expr = dplyr::sql(&amp;quot;first(temp, true)&amp;quot;),
    partition = &amp;quot;year&amp;quot;,
    order = &amp;quot;month&amp;quot;,
    frame = c(0, Inf),
    con = sc
  )
)
# # Source: spark&amp;lt;?&amp;gt; [?? x 5]
#     year month  temp tempLOCF tempNOCB
#    &amp;lt;int&amp;gt; &amp;lt;int&amp;gt; &amp;lt;dbl&amp;gt;    &amp;lt;dbl&amp;gt;    &amp;lt;dbl&amp;gt;
#  1  2016     1   6.9      6.9      6.9
#  2  2016     2  NA        6.9     10.1
#  3  2016     3  10.1     10.1     10.1
#  4  2016     4  11.5     11.5     11.5
#  5  2016     5  16.3     16.3     16.3
#  6  2016     6  19.1     19.1     19.1
#  7  2016     7  NA       19.1     17.6
#  8  2016     8  NA       19.1     17.6
#  9  2016     9  17.6     17.6     17.6
# 10  2016    10  13.6     13.6     13.6
# # … with more rows&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For what it’s worth, this functionality very recently became available via the &lt;code&gt;tidyr::fill()&lt;/code&gt;, for which there is now a &lt;a href=&#34;https://dbplyr.tidyverse.org/reference/fill.tbl_lazy.html&#34;&gt;&lt;code&gt;tbl_lazy&lt;/code&gt; method&lt;/a&gt; in {dbplyr}.&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Using Functions As An Input To Functions With {dbplyr}</title>
      <link>/2021/02/18/using-functions-as-an-input-to-functions-with-dbplyr/</link>
      <pubDate>Thu, 18 Feb 2021 20:12:00 -0500</pubDate>
      
      <guid>/2021/02/18/using-functions-as-an-input-to-functions-with-dbplyr/</guid>
      <description>
&lt;script src=&#34;/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;the-problem&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;The Problem&lt;/h1&gt;
&lt;p&gt;I wish to write a function that can mutate a column of my data using a function which is passed as an input. For example, I want to write a function which can modify an existing &lt;code&gt;tbl_spark&lt;/code&gt; using &lt;code&gt;dplyr::mutate()&lt;/code&gt; by adding a column that is the &lt;code&gt;mean()&lt;/code&gt; of a column. To do this, we will see that we require a different solution depending on whether we are working with a &lt;code&gt;data.frame&lt;/code&gt; or a &lt;code&gt;tbl_spark&lt;/code&gt;. For this reason, I am going to define an S3 generic, &lt;code&gt;mutate_with()&lt;/code&gt;, for which I am going to define two methods, one for &lt;code&gt;data.frame&lt;/code&gt;s and one for &lt;code&gt;tbl_spark&lt;/code&gt;s.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-for-data.frames&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Solution For &lt;code&gt;data.frame&lt;/code&gt;s&lt;/h1&gt;
&lt;p&gt;First of all, let us define our generic. If you are not familiar with S3 generics and how they work, I would recommend checking out the S3 section in the freely available &lt;a href=&#34;https://adv-r.hadley.nz/s3.html&#34;&gt;Advanced R book&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mutate_with &amp;lt;- function(data, fn, col_in, col_out = &amp;quot;output&amp;quot;) {
  UseMethod(generic = &amp;quot;mutate_with&amp;quot;, object = data)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now that we have our generic in place, we can add our first method for &lt;code&gt;data.frame&lt;/code&gt;s. This is actually relatively simple as seen below.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mutate_with.data.frame &amp;lt;- function(data, fn, col_in, col_out = &amp;quot;output&amp;quot;) {
  dplyr::mutate(.data = data, !!col_out := fn(!!rlang::sym(col_in)))
}
head(
  mutate_with(data = mtcars, fn = mean, col_in = &amp;quot;mpg&amp;quot;, col_out = &amp;quot;mean_mpg&amp;quot;)
)
#    mpg cyl disp  hp drat    wt  qsec vs am gear carb mean_mpg
# 1 21.0   6  160 110 3.90 2.620 16.46  0  1    4    4 20.09062
# 2 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4 20.09062
# 3 22.8   4  108  93 3.85 2.320 18.61  1  1    4    1 20.09062
# 4 21.4   6  258 110 3.08 3.215 19.44  1  0    3    1 20.09062
# 5 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2 20.09062
# 6 18.1   6  225 105 2.76 3.460 20.22  1  0    3    1 20.09062&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This works because what we are essentially doing is assigning the function &lt;code&gt;mean()&lt;/code&gt; to the object &lt;code&gt;fn&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mean
# function (x, ...) 
# UseMethod(&amp;quot;mean&amp;quot;)
# &amp;lt;bytecode: 0x7fd5f69a3590&amp;gt;
# &amp;lt;environment: namespace:base&amp;gt;
fn &amp;lt;- mean
fn
# function (x, ...) 
# UseMethod(&amp;quot;mean&amp;quot;)
# &amp;lt;bytecode: 0x7fd5f69a3590&amp;gt;
# &amp;lt;environment: namespace:base&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This means that we can call &lt;code&gt;fn()&lt;/code&gt; as if we were calling &lt;code&gt;mean()&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;fn(rnorm(100))
# [1] 0.01109211&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-for-tbl_sparks&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Solution For &lt;code&gt;tbl_spark&lt;/code&gt;s&lt;/h1&gt;
&lt;p&gt;Unfortunately the above solution does not work for &lt;code&gt;tbl_spark&lt;/code&gt;s. To show this, I will first create a Spark connection and upload the &lt;code&gt;mtcars&lt;/code&gt; data.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;sc &amp;lt;- sparklyr::spark_connect(master = &amp;quot;local&amp;quot;)
mtcars_spark &amp;lt;- dplyr::copy_to(sc, mtcars, &amp;quot;mtcars&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now let’s try calling our function with the &lt;code&gt;mtcars_spark&lt;/code&gt; object.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mutate_with.tbl_spark &amp;lt;- mutate_with.data.frame
mutate_with(
  data = mtcars_spark, fn = mean, col_in = &amp;quot;mpg&amp;quot;, col_out = &amp;quot;mean_mpg&amp;quot;
)
# Error: org.apache.spark.sql.AnalysisException: Undefined function: &amp;#39;fn&amp;#39;.
# This function is neither a registered temporary function nor a permanent
# function registered in the database &amp;#39;default&amp;#39;.; line 1 pos 85
# ... (additional output has been removed)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So we get an error here telling us that we have passed an underfined function, &lt;code&gt;fn&lt;/code&gt;. This is because in the background, the package {dbplyr} is attempting to translate our code to Spark SQL code to be executed by Spark. To do this, {dbplyr} parses our {dplyr} code, for which there are two parts.&lt;/p&gt;
&lt;p&gt;Firstly there is the translation of {dplyr} verbs, e.g. &lt;code&gt;select()&lt;/code&gt;, &lt;code&gt;filter()&lt;/code&gt;, &lt;code&gt;arrange()&lt;/code&gt;, etc. form the basic structure of a SQL query, &lt;code&gt;SELECT&lt;/code&gt;, &lt;code&gt;WHERE&lt;/code&gt;, &lt;code&gt;ORDER BY&lt;/code&gt;, etc.&lt;/p&gt;
&lt;p&gt;Secondly there is the translation of the expressions within those verbs. This is the part that is interesting to us for this blog post. First of all we have “known functions” where {dbplyr} takes the functionality that you pass to it and tries to convert it to a SQL equivalent. As a simple example, {dbplyr} will convert the &lt;code&gt;mean()&lt;/code&gt; function to &lt;code&gt;AVG&lt;/code&gt;. However {dbplyr} cannot always produce a perfect translation because there are functions which exist in R that do not exist in the varying flavours of SQL, we will refer to these as “unknown functions”.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;As a note, there is even functionality in both that cannot be translated, for example the &lt;code&gt;trim&lt;/code&gt; parameter of the &lt;code&gt;mean()&lt;/code&gt; function is not available in SQL.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;What {dbplyr} does with these unknown functions, therefore, is to leave them “as-is”. This means that database functions that are not covered by {dbplyr} can be used directly. For example in Spark we can access and use &lt;a href=&#34;https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF&#34;&gt;Hive UDFs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So what does this all mean? And why does this mean that our function failed? Well it’s because when {dbplyr} parses our code, it “sees” the &lt;code&gt;fn&lt;/code&gt; parameter and it treats it “as-is” since there is no direct conversion to a SQL function defined in {dbplyr}. Equally, there is no function in Spark SQL called &lt;code&gt;fn()&lt;/code&gt; which is why, when our converted code is sent to Spark, we see the failure. We can see this in action by rendering the translated output that {dbplyr} gives us.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;out &amp;lt;- mutate_with(
  data = mtcars_spark, fn = mean, col_in = &amp;quot;mpg&amp;quot;, col_out = &amp;quot;mean_mpg&amp;quot;
)
dbplyr::sql_render(out)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;SQL&amp;gt; SELECT `mpg`, `cyl`, `disp`, `hp`, `drat`, `wt`, `qsec`, `vs`, `am`,
`gear`, `carb`, fn(`mpg`) AS `mean_mpg`
FROM `mtcars`&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This means that we must pass the actual function &lt;em&gt;name&lt;/em&gt;, i.e. &lt;code&gt;mean&lt;/code&gt;, in place of &lt;code&gt;fn&lt;/code&gt; at the time that {dbplyr} “sees” our code and attempts to parse and translate it into SQL. For this, we need to use non-standard evaluation semantics.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mutate_with.tbl_spark &amp;lt;- function(data, fn, col_in, col_out = &amp;quot;output&amp;quot;) {
  fn &amp;lt;- rlang::enquo(fn)
  dplyr::mutate(
    .data = data, !!col_out := rlang::call2(.fn = !!fn, rlang::sym(col_in))
  )
}
mutate_with(
  data = mtcars_spark, fn = mean, col_in = &amp;quot;mpg&amp;quot;, col_out = &amp;quot;mean_mpg&amp;quot;
)
# # Source: spark&amp;lt;?&amp;gt; [?? x 12]
#      mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb mean_mpg
#    &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt;    &amp;lt;dbl&amp;gt;
#  1  21       6  160    110  3.9   2.62  16.5     0     1     4     4     20.1
#  2  21       6  160    110  3.9   2.88  17.0     0     1     4     4     20.1
#  3  22.8     4  108     93  3.85  2.32  18.6     1     1     4     1     20.1
#  4  21.4     6  258    110  3.08  3.22  19.4     1     0     3     1     20.1
#  5  18.7     8  360    175  3.15  3.44  17.0     0     0     3     2     20.1
#  6  18.1     6  225    105  2.76  3.46  20.2     1     0     3     1     20.1
#  7  14.3     8  360    245  3.21  3.57  15.8     0     0     3     4     20.1
#  8  24.4     4  147.    62  3.69  3.19  20       1     0     4     2     20.1
#  9  22.8     4  141.    95  3.92  3.15  22.9     1     0     4     2     20.1
# 10  19.2     6  168.   123  3.92  3.44  18.3     1     0     4     4     20.1
# # … with more rows&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So why does this work? Well what we are doing here is “quoting” the parameter &lt;code&gt;fn&lt;/code&gt; which is the same as saying preventing the evaluation of &lt;code&gt;fn&lt;/code&gt;. &lt;code&gt;rlang::enquo()&lt;/code&gt; is used to quote function arguments such as &lt;code&gt;fn&lt;/code&gt; and returns what is known as a “quosure”. A “quosure” is an object containing both the expression and the environment which that expression comes from. We can “unquote” the “quosure”, &lt;code&gt;fn&lt;/code&gt;, with the &lt;code&gt;!!&lt;/code&gt; or “bang-bang” operator.&lt;/p&gt;
&lt;p&gt;In English this means that we can evaluate and replace inline the captured expression. So what &lt;code&gt;!!fn&lt;/code&gt; actually reads as is &lt;code&gt;mean&lt;/code&gt;. The &lt;code&gt;!!fn&lt;/code&gt; works because it is evaluated &lt;em&gt;before&lt;/em&gt; any R code is evaluated. In other words, before the code is parsed by {dbplyr}, {rlang} is able to evaluate &lt;code&gt;!!fn&lt;/code&gt;, replacing it with &lt;code&gt;mean&lt;/code&gt;. You will sometimes see this being referred to as partial evaluation.&lt;/p&gt;
&lt;p&gt;That’s a lot of information in two short paragraphs and I’d highly recommend reading the help file (&lt;code&gt;?rlang::quosure&lt;/code&gt;) if you’d like to know more. Another great resource for learning more about {rlang} is Brodie Gaslam’s &lt;a href=&#34;https://www.brodieg.com/2020/08/11/quosures/&#34;&gt;On Quosures&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We use &lt;code&gt;rlang::call2()&lt;/code&gt; to build a quoted function call which can be interpreted by {dbplyr}. What this all boils down to is that &lt;code&gt;rlang::call2(.fn = !!fn, rlang::sym(col_in))&lt;/code&gt; is used to create the following, unevaluated, expression.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mean(mpg)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So the execution order is as follows:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;&lt;code&gt;!!fn&lt;/code&gt; is translated to &lt;code&gt;mean&lt;/code&gt;, inline.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rlang::call2()&lt;/code&gt; is evaluated, giving &lt;code&gt;mean(mpg)&lt;/code&gt; (note that we convert our string input to a symbol using &lt;code&gt;rlang::sym(col_in)&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;{dbplyr} translates the code to SQL code and sends it to Spark to be executed.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Note that we can achieve a similar result using &lt;code&gt;base::bquote()&lt;/code&gt; and &lt;code&gt;base::eval()&lt;/code&gt;. &lt;code&gt;bquote()&lt;/code&gt; is base R’s equivalent of partial evaluation which creates a quoted expression that we can then evaulate with &lt;code&gt;eval()&lt;/code&gt;. The difference in syntax is that the parts to be partially evaluated are surrounded by &lt;code&gt;.()&lt;/code&gt; instead of &lt;code&gt;!!&lt;/code&gt; as in {rlang}.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mutate_with_bquote &amp;lt;- function(data, fn, col_in, col_out = &amp;quot;output&amp;quot;) {
  eval(bquote(
    dplyr::mutate(.data = data, !!col_out := .(fn)(rlang::sym(col_in)))
  ))
}
mutate_with_bquote(
  data = mtcars_spark, fn = mean, col_in = &amp;quot;mpg&amp;quot;, col_out = &amp;quot;mean_mpg&amp;quot;
)
# # Source: spark&amp;lt;?&amp;gt; [?? x 12]
#      mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb mean_mpg
#    &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt;    &amp;lt;dbl&amp;gt;
#  1  21       6  160    110  3.9   2.62  16.5     0     1     4     4     20.1
#  2  21       6  160    110  3.9   2.88  17.0     0     1     4     4     20.1
#  3  22.8     4  108     93  3.85  2.32  18.6     1     1     4     1     20.1
#  4  21.4     6  258    110  3.08  3.22  19.4     1     0     3     1     20.1
#  5  18.7     8  360    175  3.15  3.44  17.0     0     0     3     2     20.1
#  6  18.1     6  225    105  2.76  3.46  20.2     1     0     3     1     20.1
#  7  14.3     8  360    245  3.21  3.57  15.8     0     0     3     4     20.1
#  8  24.4     4  147.    62  3.69  3.19  20       1     0     4     2     20.1
#  9  22.8     4  141.    95  3.92  3.15  22.9     1     0     4     2     20.1
# 10  19.2     6  168.   123  3.92  3.44  18.3     1     0     4     4     20.1
# # … with more rows&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;quoted-function-name&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Quoted Function Name&lt;/h1&gt;
&lt;p&gt;The above could have all been made much simpler by passing a quoted function name, however you may well have reasons you don’t wish to do this. For completeness, I present an example of how this can be done.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mutate_with.tbl_spark &amp;lt;- function(data, fn, col_in, col_out = &amp;quot;output&amp;quot;) {
  condition &amp;lt;- paste0(fn, &amp;quot;(&amp;quot;, col_in, &amp;quot;)&amp;quot;)
  dplyr::mutate(.data = data, !!col_out := !!rlang::parse_expr(condition))
}
mutate_with(
  data = mtcars_spark, fn = &amp;quot;mean&amp;quot;, col_in = &amp;quot;mpg&amp;quot;, col_out = &amp;quot;mean_mpg&amp;quot;
)
# # Source: spark&amp;lt;?&amp;gt; [?? x 12]
#      mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb mean_mpg
#    &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt;    &amp;lt;dbl&amp;gt;
#  1  21       6  160    110  3.9   2.62  16.5     0     1     4     4     20.1
#  2  21       6  160    110  3.9   2.88  17.0     0     1     4     4     20.1
#  3  22.8     4  108     93  3.85  2.32  18.6     1     1     4     1     20.1
#  4  21.4     6  258    110  3.08  3.22  19.4     1     0     3     1     20.1
#  5  18.7     8  360    175  3.15  3.44  17.0     0     0     3     2     20.1
#  6  18.1     6  225    105  2.76  3.46  20.2     1     0     3     1     20.1
#  7  14.3     8  360    245  3.21  3.57  15.8     0     0     3     4     20.1
#  8  24.4     4  147.    62  3.69  3.19  20       1     0     4     2     20.1
#  9  22.8     4  141.    95  3.92  3.15  22.9     1     0     4     2     20.1
# 10  19.2     6  168.   123  3.92  3.44  18.3     1     0     4     4     20.1
# # … with more rows&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So we build the expression as a string which we then parse ourselves using &lt;code&gt;rlang::parse_expr()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It is also worth noting that this version works with regular &lt;code&gt;data.frame&lt;/code&gt;s too.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mutate_with.data.frame &amp;lt;- function(data, fn, col_in, col_out = &amp;quot;output&amp;quot;) {
  condition &amp;lt;- paste0(fn, &amp;quot;(&amp;quot;, col_in, &amp;quot;)&amp;quot;)
  dplyr::mutate(.data = data, !!col_out := !!rlang::parse_expr(condition))
}
head(mutate_with(
  data = mtcars, fn = &amp;quot;mean&amp;quot;, col_in = &amp;quot;mpg&amp;quot;, col_out = &amp;quot;mean_mpg&amp;quot;
))
#    mpg cyl disp  hp drat    wt  qsec vs am gear carb mean_mpg
# 1 21.0   6  160 110 3.90 2.620 16.46  0  1    4    4 20.09062
# 2 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4 20.09062
# 3 22.8   4  108  93 3.85 2.320 18.61  1  1    4    1 20.09062
# 4 21.4   6  258 110 3.08 3.215 19.44  1  0    3    1 20.09062
# 5 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2 20.09062
# 6 18.1   6  225 105 2.76 3.460 20.22  1  0    3    1 20.09062&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;additional-comments&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Additional Comments&lt;/h1&gt;
&lt;p&gt;What is nice about the solution presented in this blog post is that we can still pass any user defined functions. Let’s say we have a function written in Scala code and exposed to the Spark cluster. We can still call this function. For example below I am using the Hive UDF, &lt;code&gt;reverse()&lt;/code&gt;, to return a column with my last name spelt backwards.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;data &amp;lt;- data.frame(first_name = &amp;quot;nathan&amp;quot;, last_name = &amp;quot;eastwood&amp;quot;)
data &amp;lt;- dplyr::copy_to(sc, data, &amp;quot;data&amp;quot;)
mutate_with(data = data, fn = reverse, col_in = &amp;quot;last_name&amp;quot;)
# # Source: spark&amp;lt;?&amp;gt; [?? x 3]
#   first_name last_name output  
#   &amp;lt;chr&amp;gt;      &amp;lt;chr&amp;gt;     &amp;lt;chr&amp;gt;   
# 1 nathan     eastwood  doowtsae&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In addition it can be a nice way to get around &lt;code&gt;R CMD check&lt;/code&gt; issues. Let’s say we wanted to use the Spark function &lt;code&gt;sequence()&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;add_sequence &amp;lt;- function(data, length_to, col_out = &amp;quot;seq&amp;quot;) {
  dplyr::mutate(.data = data, !!col_out := sequence(1, length_to))
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we have the above function defined in an R package, we may see the following &lt;code&gt;R CMD check NOTE&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;checking R code for possible problems ... NOTE
add_sequence: possible error in sequence(1,
  length_to): unused argument (length_to)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Whereas using the trick shown in this blog, we no longer see this issue.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;add_sequence &amp;lt;- function(data, fn = sequence, from, to, col_out = &amp;quot;seq&amp;quot;) {
  fun &amp;lt;- rlang::enquo(fn)
  dplyr::mutate(.data = data, !!col_out := rlang::call2(.fn = !!fun, from, to))
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Of course, I wouldn’t recommend defining such a function this way.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;To keep things short and sweet, if you wish to pass a function as-is to another function which you then wish to have parsed by dbplyr into SQL code, you must first quote the function with &lt;code&gt;rlang::enquo()&lt;/code&gt; and then unquote it with &lt;code&gt;!!&lt;/code&gt;. You can then build your expression with &lt;code&gt;rlang::call2()&lt;/code&gt; and have this parsed by {dbplyr}.&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>poorman: Versions 0.2.2 and 0.2.3 Releases</title>
      <link>/2020/11/14/poorman-versions-0.2.2-and-0.2.3-releases/</link>
      <pubDate>Sat, 14 Nov 2020 20:12:00 -0500</pubDate>
      
      <guid>/2020/11/14/poorman-versions-0.2.2-and-0.2.3-releases/</guid>
      <description>
&lt;script src=&#34;/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;introduction&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Welcome to my series of blog posts about my data manipulation package, {poorman}. For those of you that don’t know, {poorman} is aiming to be a replication of {dplyr} but using only {base} R, and therefore be completely dependency free. What’s nice about this series is that if you would rather just use {dplyr}, then that’s absolutely OK! By highlighting {poorman} functionality, this series of blog posts simultaneously highlights {dplyr} functionality too! However I sometimes also describe how I developed the internals of {poorman}, often highlighting useful {base} R tips and tricks.&lt;/p&gt;
&lt;p&gt;Since my last blog post about {poorman}, versions 0.2.2 and 0.2.3 have been released, bringing with them a whole host of new functions and features. In today’s blog post we will be taking a look at some of these new features. Given the sheer amount of features this release brings, we won’t be focusing on the internals of any of these functions. Instead, we will simply be taking a look at what some of them can do.&lt;/p&gt;
&lt;div id=&#34;across&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;across()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;One of the newer features in {dplyr}, &lt;code&gt;across()&lt;/code&gt; is intended to eventually replace the scoped variants (&lt;code&gt;_if&lt;/code&gt;, &lt;code&gt;_at&lt;/code&gt;, &lt;code&gt;_all&lt;/code&gt;) of the “single table” verb functions which have now been superseded. These functions will supposedly remain within {dplyr} for “several years” still, giving developers plenty of time to update their code.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;across()&lt;/code&gt; makes it easy to apply the same transformation to multiple columns, allowing you to use &lt;code&gt;poor-select&lt;/code&gt; (or &lt;code&gt;tidy-select&lt;/code&gt;) semantics inside of &lt;code&gt;summarise()&lt;/code&gt; and &lt;code&gt;mutate()&lt;/code&gt;. Let’s take a look at the function in action.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(poorman, warn.conflicts = FALSE)
iris %&amp;gt;%
  group_by(Species) %&amp;gt;%
  summarise(across(.cols = starts_with(&amp;quot;Sepal&amp;quot;), .fn = mean))
#      Species Sepal.Length Sepal.Width
# 1     setosa        5.006       3.428
# 2 versicolor        5.936       2.770
# 3  virginica        6.588       2.974&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the above code chunk, we take the iris dataset and group it by the &lt;code&gt;Species&lt;/code&gt; column; then we look to summarise across all columns which start with the string &lt;code&gt;&#34;Sepal&#34;&lt;/code&gt; (&lt;code&gt;Sepal.Length&lt;/code&gt; and &lt;code&gt;Sepal.Width&lt;/code&gt;) by taking the mean of those columns within each &lt;code&gt;Species&lt;/code&gt; group. Let’s take a look at a more complex example.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;iris %&amp;gt;%
  group_by(Species) %&amp;gt;%
  summarise(across(.cols = contains(&amp;quot;Width&amp;quot;), .fn = list(mean, sd)))
#      Species Sepal.Width_1 Sepal.Width_2 Petal.Width_1 Petal.Width_2
# 1     setosa         3.428     0.3790644         0.246     0.1053856
# 2 versicolor         2.770     0.3137983         1.326     0.1977527
# 3  virginica         2.974     0.3224966         2.026     0.2746501&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So here, we are saying give me the mean and standard devitaion across all columns containing the string &lt;code&gt;&#34;Width&#34;&lt;/code&gt; for each &lt;code&gt;Species&lt;/code&gt; of iris flower. Notice how the output is named, the function will give the columns numbers to represent the functional output, i.e. here &lt;code&gt;_1&lt;/code&gt; represents the mean and &lt;code&gt;_2&lt;/code&gt; represents the standard deviation. You can control the names yourself but providing them to the &lt;code&gt;.names&lt;/code&gt; argument.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;iris %&amp;gt;%
  group_by(Species) %&amp;gt;%
  summarise(across(
    .cols = contains(&amp;quot;Width&amp;quot;),
    .fn = list(mean, sd),
    .names = c(
      &amp;quot;sepal_width_mean&amp;quot;, &amp;quot;sepal_width_sd&amp;quot;, &amp;quot;petal_width_mean&amp;quot;, &amp;quot;petal_width_sd&amp;quot;
    )
  ))
#      Species sepal_width_mean sepal_width_sd petal_width_mean petal_width_sd
# 1     setosa            3.428      0.3790644            0.246      0.1053856
# 2 versicolor            2.770      0.3137983            1.326      0.1977527
# 3  virginica            2.974      0.3224966            2.026      0.2746501&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is slightly different to how {dplyr} works since it imports {glue}, but remember, {poorman} aims to be dependency free. This functionality will be expanded upon in future releases of {poorman}.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;case_when&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;case_when()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;This function allows you to vectorise multiple &lt;code&gt;if_else()&lt;/code&gt; statements. It is an R equivalent of the SQL &lt;code&gt;CASE WHEN&lt;/code&gt; statement. If no cases match, &lt;code&gt;NA&lt;/code&gt; is returned. The syntax for the function is a sequence of two-sided formulas. The left hand side determines which values match the particular case whereas the right hand side provides the replacement value.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;x &amp;lt;- 1:50
case_when(
  x %% 35 == 0 ~ &amp;quot;fizz buzz&amp;quot;,
  x %% 5 == 0 ~ &amp;quot;fizz&amp;quot;,
  x %% 7 == 0 ~ &amp;quot;buzz&amp;quot;,
  TRUE ~ as.character(x)
)
#  [1] &amp;quot;1&amp;quot;         &amp;quot;2&amp;quot;         &amp;quot;3&amp;quot;         &amp;quot;4&amp;quot;         &amp;quot;fizz&amp;quot;      &amp;quot;6&amp;quot;         &amp;quot;buzz&amp;quot;     
#  [8] &amp;quot;8&amp;quot;         &amp;quot;9&amp;quot;         &amp;quot;fizz&amp;quot;      &amp;quot;11&amp;quot;        &amp;quot;12&amp;quot;        &amp;quot;13&amp;quot;        &amp;quot;buzz&amp;quot;     
# [15] &amp;quot;fizz&amp;quot;      &amp;quot;16&amp;quot;        &amp;quot;17&amp;quot;        &amp;quot;18&amp;quot;        &amp;quot;19&amp;quot;        &amp;quot;fizz&amp;quot;      &amp;quot;buzz&amp;quot;     
# [22] &amp;quot;22&amp;quot;        &amp;quot;23&amp;quot;        &amp;quot;24&amp;quot;        &amp;quot;fizz&amp;quot;      &amp;quot;26&amp;quot;        &amp;quot;27&amp;quot;        &amp;quot;buzz&amp;quot;     
# [29] &amp;quot;29&amp;quot;        &amp;quot;fizz&amp;quot;      &amp;quot;31&amp;quot;        &amp;quot;32&amp;quot;        &amp;quot;33&amp;quot;        &amp;quot;34&amp;quot;        &amp;quot;fizz buzz&amp;quot;
# [36] &amp;quot;36&amp;quot;        &amp;quot;37&amp;quot;        &amp;quot;38&amp;quot;        &amp;quot;39&amp;quot;        &amp;quot;fizz&amp;quot;      &amp;quot;41&amp;quot;        &amp;quot;buzz&amp;quot;     
# [43] &amp;quot;43&amp;quot;        &amp;quot;44&amp;quot;        &amp;quot;fizz&amp;quot;      &amp;quot;46&amp;quot;        &amp;quot;47&amp;quot;        &amp;quot;48&amp;quot;        &amp;quot;buzz&amp;quot;     
# [50] &amp;quot;fizz&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Like an if statement, the arguments are evaluated in order, so you must proceed from the most specific to the most general. &lt;code&gt;case_when()&lt;/code&gt; is particularly useful inside &lt;code&gt;mutate()&lt;/code&gt; when you want to create a new variable that relies on a complex combination of existing variables.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars %&amp;gt;%
  mutate(efficient = case_when(mpg &amp;gt; 25 ~ TRUE, TRUE ~ FALSE))
#                      mpg cyl  disp  hp drat    wt  qsec vs am gear carb efficient
# Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4     FALSE
# Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4     FALSE
# Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1     FALSE
# Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1     FALSE
# Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2     FALSE
# Valiant             18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1     FALSE
# Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4     FALSE
# Merc 240D           24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2     FALSE
# Merc 230            22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2     FALSE
# Merc 280            19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4     FALSE
# Merc 280C           17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4     FALSE
# Merc 450SE          16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3     FALSE
# Merc 450SL          17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3     FALSE
# Merc 450SLC         15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3     FALSE
# Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4     FALSE
# Lincoln Continental 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4     FALSE
# Chrysler Imperial   14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4     FALSE
# Fiat 128            32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1      TRUE
# Honda Civic         30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2      TRUE
# Toyota Corolla      33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1      TRUE
# Toyota Corona       21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1     FALSE
# Dodge Challenger    15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2     FALSE
# AMC Javelin         15.2   8 304.0 150 3.15 3.435 17.30  0  0    3    2     FALSE
# Camaro Z28          13.3   8 350.0 245 3.73 3.840 15.41  0  0    3    4     FALSE
# Pontiac Firebird    19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2     FALSE
# Fiat X1-9           27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1      TRUE
# Porsche 914-2       26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2      TRUE
# Lotus Europa        30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2      TRUE
# Ford Pantera L      15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4     FALSE
# Ferrari Dino        19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6     FALSE
# Maserati Bora       15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8     FALSE
# Volvo 142E          21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2     FALSE&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;rename_with&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;rename_with()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;rename_with()&lt;/code&gt; acts like &lt;code&gt;rename()&lt;/code&gt;, only it allows you to rename columns with a function. In the below example, we rename the columns of &lt;code&gt;iris&lt;/code&gt; to be upper case.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;rename_with(iris, toupper) %&amp;gt;% head()
#   SEPAL.LENGTH SEPAL.WIDTH PETAL.LENGTH PETAL.WIDTH SPECIES
# 1          5.1         3.5          1.4         0.2  setosa
# 2          4.9         3.0          1.4         0.2  setosa
# 3          4.7         3.2          1.3         0.2  setosa
# 4          4.6         3.1          1.5         0.2  setosa
# 5          5.0         3.6          1.4         0.2  setosa
# 6          5.4         3.9          1.7         0.4  setosa&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However we can have more control over which columns we rename by making use of the &lt;code&gt;.cols&lt;/code&gt; parameter and &lt;code&gt;poor-select&lt;/code&gt; selection semantics.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;rename_with(iris, toupper, contains(&amp;quot;Petal&amp;quot;)) %&amp;gt;% head()
#   Sepal.Length Sepal.Width PETAL.LENGTH PETAL.WIDTH Species
# 1          5.1         3.5          1.4         0.2  setosa
# 2          4.9         3.0          1.4         0.2  setosa
# 3          4.7         3.2          1.3         0.2  setosa
# 4          4.6         3.1          1.5         0.2  setosa
# 5          5.0         3.6          1.4         0.2  setosa
# 6          5.4         3.9          1.7         0.4  setosa&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;This post has demonstrated some of the capabilities of the {poorman} (and therefore {dplyr}) package. The v0.2.2 and v0.2.3 releases actually includes plenty more features and functions so be sure to check out the &lt;a href=&#34;https://github.com/nathaneastwood/poorman/releases&#34;&gt;release page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you are interested in taking a closer look at how have coded these functions, you can see the code on the relevant {poorman} &lt;a href=&#34;https://github.com/nathaneastwood/poorman&#34;&gt;GitHub page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you’d like to show your support for {poorman}, please consider giving the package a &lt;a href=&#34;https://github.com/nathaneastwood/poorman/stargazers&#34;&gt;Star on Github&lt;/a&gt; as it gives me that boost of dopamine needed to continue development.&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>poorman: Version 0.2.1 Release</title>
      <link>/2020/07/01/poorman-version-0.2.1-release/</link>
      <pubDate>Wed, 01 Jul 2020 20:12:00 -0500</pubDate>
      
      <guid>/2020/07/01/poorman-version-0.2.1-release/</guid>
      <description>
&lt;script src=&#34;/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;introduction&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Welcome to my series of blog posts about my data manipulation package, &lt;code&gt;{poorman}&lt;/code&gt;. For those of you that don’t know, &lt;code&gt;{poorman}&lt;/code&gt; is aiming to be a replication of &lt;code&gt;{dplyr}&lt;/code&gt; but using only &lt;code&gt;{base}&lt;/code&gt; R, and therefore be completely dependency free. What’s nice about this series is that if you would rather just use &lt;code&gt;{dplyr}&lt;/code&gt;, then that’s absolutely OK! By highlighting &lt;code&gt;{poorman}&lt;/code&gt; functionality, this series of blog posts simultaneously highlights &lt;code&gt;{dplyr}&lt;/code&gt; functionality too! However I sometimes also describe how I developed the internals of &lt;code&gt;{poorman}&lt;/code&gt;, often highlighting useful &lt;code&gt;{base}&lt;/code&gt; R tips and tricks.&lt;/p&gt;
&lt;p&gt;Today marks the release of v0.2.1 of &lt;code&gt;{poorman}&lt;/code&gt; and with it a whole host of new functions and features. In today’s blog post we will be taking a look at some of these new features. Given the sheer amount of features this release brings, we won’t be focusing on the internals of any of these functions; the internals will be saved for another post. In stead, we will simply be taking a look at what some of them can do.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;selecting-distinct-rows&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Selecting Distinct Rows&lt;/h1&gt;
&lt;p&gt;The first function we will take a look at is &lt;code&gt;distinct()&lt;/code&gt;. Let’s say you want to select only the distinct, or unique, rows from your &lt;code&gt;data.frame&lt;/code&gt;, &lt;code&gt;distinct()&lt;/code&gt; will help you do that. Let’s create some fake data; some are duplicated.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;df &amp;lt;- data.frame(
  id = c(1, 2, 3, 4, 5, 6, 1, 2, 7, 1, 4, 6),
  age = c(26, 24, 26, 22, 23, 24, 26, 24, 22, 26, 22, 25),
  score = c(85, 63, 55, 74, 31, 77, 85, 63, 42, 85, 74, 78)
)
df
#    id age score
# 1   1  26    85
# 2   2  24    63
# 3   3  26    55
# 4   4  22    74
# 5   5  23    31
# 6   6  24    77
# 7   1  26    85
# 8   2  24    63
# 9   7  22    42
# 10  1  26    85
# 11  4  22    74
# 12  6  25    78&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we wish to see the distinct records from this data.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(poorman, warn.conflicts = FALSE)
df %&amp;gt;% distinct()
#    id age score
# 1   1  26    85
# 2   2  24    63
# 3   3  26    55
# 4   4  22    74
# 5   5  23    31
# 6   6  24    77
# 9   7  22    42
# 12  6  25    78&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So we see that we now only have 8 records out of the original 12 because the duplicates have been removed. We can actually obtain the distinct rows for a particular column, returning just that column.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;df %&amp;gt;% distinct(age)
#    age
# 1   26
# 2   24
# 4   22
# 5   23
# 12  25&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But if you need the other variables still, you can choose to keep those too.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;df %&amp;gt;% distinct(age, .keep_all = TRUE)
#    id age score
# 1   1  26    85
# 2   2  24    63
# 4   4  22    74
# 5   5  23    31
# 12  6  25    78&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;slicing-data&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Slicing Data&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;{dplyr}&lt;/code&gt; provides a couple of ways to selecting a subset of rows. It has the functions &lt;code&gt;top_n()&lt;/code&gt; and &lt;code&gt;top_frac()&lt;/code&gt; as well as the &lt;code&gt;slice_*()&lt;/code&gt; family of functions. The former functions have now been superseded by the latter and so &lt;code&gt;{poorman}&lt;/code&gt; skipped the implementation of the former. So what exactly do they do? Let’s take a look at some examples using the &lt;code&gt;mtcars&lt;/code&gt; dataset.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;slice_head()&lt;/code&gt; returns the first &lt;code&gt;n&lt;/code&gt; rows (defaults to 1). &lt;code&gt;slice_tail()&lt;/code&gt; returns the &lt;em&gt;last&lt;/em&gt; &lt;code&gt;n&lt;/code&gt; rows (not shown here).&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;slice_head(mtcars, n = 3)
#                mpg cyl disp  hp drat    wt  qsec vs am gear carb
# Mazda RX4     21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
# Mazda RX4 Wag 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
# Datsun 710    22.8   4  108  93 3.85 2.320 18.61  1  1    4    1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;slice_sample()&lt;/code&gt; randomly selects rows with or without replacement.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;slice_sample(mtcars, n = 3, replace = TRUE)
#                mpg cyl  disp  hp drat    wt  qsec vs am gear carb
# Porsche 914-2 26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
# Toyota Corona 21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
# Merc 280C     17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;slice_min()&lt;/code&gt; and &lt;code&gt;slice_max()&lt;/code&gt; select rows with highest or lowest values of a variable.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars %&amp;gt;% slice_min(mpg, n = 3)
#                      mpg cyl disp  hp drat    wt  qsec vs am gear carb
# Cadillac Fleetwood  10.4   8  472 205 2.93 5.250 17.98  0  0    3    4
# Lincoln Continental 10.4   8  460 215 3.00 5.424 17.82  0  0    3    4
# Camaro Z28          13.3   8  350 245 3.73 3.840 15.41  0  0    3    4&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;selecting-with-predicates&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Selecting With Predicates&lt;/h1&gt;
&lt;p&gt;It is now possible to select columns in your &lt;code&gt;data.frame&lt;/code&gt; which match a predicate such as &lt;code&gt;is.numeric()&lt;/code&gt;. &lt;code&gt;where()&lt;/code&gt; takes a function and returns all variables for which the function returns &lt;code&gt;TRUE&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;df &amp;lt;- data.frame(
  col1 = c(1, 2, 3),
  col2 = c(&amp;quot;x&amp;quot;, &amp;quot;y&amp;quot;, &amp;quot;z&amp;quot;),
  col3 = c(TRUE, FALSE, TRUE)
)
df %&amp;gt;% select(where(is.numeric))
#   col1
# 1    1
# 2    2
# 3    3&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;working-with-na-values&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Working With NA Values&lt;/h1&gt;
&lt;div id=&#34;finding-the-first-non-missing-element&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Finding the First Non-Missing Element&lt;/h2&gt;
&lt;p&gt;Given a set of vectors, the &lt;code&gt;coalesce()&lt;/code&gt; function finds the first non-missing value at each position.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Use a single value to replace all missing values
x &amp;lt;- sample(c(1:5, NA, NA, NA))
coalesce(x, 0L)
# [1] 4 0 5 0 1 2 0 3

# Or match together a complete vector from missing pieces
y &amp;lt;- c(1, 2, NA, NA, 5)
z &amp;lt;- c(NA, NA, 3, 4, 5)
coalesce(y, z)
# [1] 1 2 3 4 5&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;convert-values-to-na&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Convert Values To NA&lt;/h2&gt;
&lt;p&gt;We can convert values in a vector &lt;code&gt;x&lt;/code&gt; if they match values in a second vector &lt;code&gt;y&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;na_if(1:5, 5:1)
# [1]  1  2 NA  4  5&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is particularly useful in a &lt;code&gt;data.frame&lt;/code&gt; if you need to replace a particular value.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;df &amp;lt;- data.frame(a = c(&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;, &amp;quot;BAD_VALUE&amp;quot;))
df %&amp;gt;% mutate(a = na_if(a, &amp;quot;BAD_VALUE&amp;quot;))
#      a
# 1    a
# 2    b
# 3    c
# 4 &amp;lt;NA&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;replacing-na-values&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Replacing NA Values&lt;/h2&gt;
&lt;p&gt;Within a &lt;code&gt;data.frame&lt;/code&gt; we often have missing values in multiple columns. We sometimes wish to replace these values which is where &lt;code&gt;replace_na()&lt;/code&gt; comes in. &lt;code&gt;replace_na()&lt;/code&gt; is actually a function from the &lt;code&gt;{tidyr}&lt;/code&gt; package but I decided to add it to &lt;code&gt;{poorman}&lt;/code&gt; as it is extremely useful. Let’s take a look.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;df &amp;lt;- data.frame(x = c(1, 2, NA), y = c(&amp;quot;a&amp;quot;, NA, &amp;quot;b&amp;quot;))
df %&amp;gt;% replace_na(list(x = 0, y = &amp;quot;unknown&amp;quot;))
#   x       y
# 1 1       a
# 2 2 unknown
# 3 0       b&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;recoding-values&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Recoding Values&lt;/h1&gt;
&lt;p&gt;If we wish to replace values within a vector or a column of a &lt;code&gt;data.frame&lt;/code&gt;, we can use &lt;code&gt;recode()&lt;/code&gt;. This is a vectorised version of &lt;code&gt;base::switch()&lt;/code&gt;: you can replace numeric values based on their position or their name, and character or factor values only by their name.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;char_vec &amp;lt;- sample(c(&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;), 10, replace = TRUE)
recode(char_vec, a = &amp;quot;Apple&amp;quot;)
#  [1] &amp;quot;b&amp;quot;     &amp;quot;c&amp;quot;     &amp;quot;b&amp;quot;     &amp;quot;c&amp;quot;     &amp;quot;Apple&amp;quot; &amp;quot;Apple&amp;quot; &amp;quot;Apple&amp;quot; &amp;quot;c&amp;quot;     &amp;quot;Apple&amp;quot; &amp;quot;b&amp;quot;
recode(char_vec, a = &amp;quot;Apple&amp;quot;, b = &amp;quot;Banana&amp;quot;)
#  [1] &amp;quot;Banana&amp;quot; &amp;quot;c&amp;quot;      &amp;quot;Banana&amp;quot; &amp;quot;c&amp;quot;      &amp;quot;Apple&amp;quot;  &amp;quot;Apple&amp;quot;  &amp;quot;Apple&amp;quot;  &amp;quot;c&amp;quot;      &amp;quot;Apple&amp;quot; 
# [10] &amp;quot;Banana&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;group-details&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Group Details&lt;/h1&gt;
&lt;p&gt;The final group (no pun intended) of features are focussed solely on grouped data. Given how many there are, I am not going to go into detail and instead I provide a brief overview here for the reader. The plan is to detail these functions in a separate blog post since a lot of work went on under the hood that may be interesting to discuss.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Functions for splitting &lt;code&gt;data.frame&lt;/code&gt;s: &lt;code&gt;group_split()&lt;/code&gt;, &lt;code&gt;group_keys()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Extract grouping metadata: &lt;code&gt;group_data()&lt;/code&gt;, &lt;code&gt;group_indices()&lt;/code&gt;, &lt;code&gt;group_vars()&lt;/code&gt;, &lt;code&gt;group_rows()&lt;/code&gt;, &lt;code&gt;group_size()&lt;/code&gt;, &lt;code&gt;n_groups()&lt;/code&gt;, &lt;code&gt;groups()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Extract information about the &lt;em&gt;current&lt;/em&gt; group: &lt;code&gt;cur_data()&lt;/code&gt;, &lt;code&gt;cur_group()&lt;/code&gt;, &lt;code&gt;cur_group_id()&lt;/code&gt;, &lt;code&gt;cur_group_rows()&lt;/code&gt;, &lt;code&gt;cur_column()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;You made it this far, great! I won’t keep you much longer. This post has demonstrated some of the capabilities of the &lt;code&gt;{poorman}&lt;/code&gt; (and therefore &lt;code&gt;{dplyr}&lt;/code&gt;) package. The v0.2.1 release actually includes a sleuth of other features and functions so be sure to check out the &lt;a href=&#34;https://github.com/nathaneastwood/poorman/releases/tag/v0.2.1&#34;&gt;release page&lt;/a&gt; for a full list.&lt;/p&gt;
&lt;p&gt;As this blog post is quite long, I haven’t gone into any further details of the internals of &lt;code&gt;{poorman}&lt;/code&gt; however if you are interested in taking a closer look at how I handle the different input types, you can see the code on the relevant &lt;code&gt;{poorman}&lt;/code&gt; &lt;a href=&#34;https://github.com/nathaneastwood/poorman&#34;&gt;GitHub page&lt;/a&gt;. &lt;code&gt;{poorman}&lt;/code&gt; is still a work in progress but as you can see, it already has a lot of functionality you know and love from &lt;code&gt;{dplyr}&lt;/code&gt; so if you are working on a new project and don’t want to have to deal with dependency management, especially if you are sharing work with colleagues, why not give &lt;code&gt;{poorman}&lt;/code&gt; a try?&lt;/p&gt;
&lt;p&gt;If you’d like to show your support for &lt;code&gt;{poorman}&lt;/code&gt;, please consider giving the package a &lt;a href=&#34;https://github.com/nathaneastwood/poorman/stargazers&#34;&gt;Star on Github&lt;/a&gt; as it gives me that boost of dopamine needed to continue development.&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>poorman: The Selectificator 2000!</title>
      <link>/2020/05/17/poorman-the-selectificator-2000/</link>
      <pubDate>Sun, 17 May 2020 20:12:00 -0500</pubDate>
      
      <guid>/2020/05/17/poorman-the-selectificator-2000/</guid>
      <description>
&lt;script src=&#34;/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;introduction&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Welcome to my series of blog posts about my data manipulation package, &lt;code&gt;{poorman}&lt;/code&gt;. For those of you that don’t know, &lt;code&gt;{poorman}&lt;/code&gt; is aiming to be a replication of &lt;code&gt;{dplyr}&lt;/code&gt; but using only &lt;code&gt;{base}&lt;/code&gt; R, and therefore be completely dependency free. What’s nice about this series is that if you’re not into &lt;code&gt;{poorman}&lt;/code&gt; and would prefer just to use &lt;code&gt;{dplyr}&lt;/code&gt;, then that’s absolutely OK! By highlighting &lt;code&gt;{poorman}&lt;/code&gt; functionality, this series of blog posts simultaneously highlights &lt;code&gt;{dplyr}&lt;/code&gt; functionality too! However I also describe how I developed the internals of &lt;code&gt;{poorman}&lt;/code&gt;, often highlighting useful &lt;code&gt;{base}&lt;/code&gt; R tips and tricks.&lt;/p&gt;
&lt;p&gt;I recently released v0.2.0 of &lt;code&gt;{poorman}&lt;/code&gt; which you can install from &lt;a href=&#34;https://cran.r-project.org/web/packages/poorman/&#34;&gt;CRAN&lt;/a&gt; and so today I am going to talk about my progress in expanding the flexibility of the &lt;code&gt;select()&lt;/code&gt; function. But I’m not just going to show you what it can do, I am going to show you how. If you’re interested in learning a little bit about non-standard evaluation in R then be sure to read on.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;the-selectificator-1000&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;The Selectificator 1000&lt;/h1&gt;
&lt;p&gt;Before v0.2.0, &lt;code&gt;{poorman}&lt;/code&gt; was using a form of non-standard evaluation which converts function inputs to character strings and then uses those to figure out which columns to select. Specifically, &lt;code&gt;{poorman}&lt;/code&gt; includes the following helper function.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;deparse_dots &amp;lt;- function(...) {
  vapply(substitute(...()), deparse, NA_character_)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is an unexported function since it is not user facing but you can find it in the code on GitHub &lt;a href=&#34;https://github.com/nathaneastwood/poorman/blob/master/R/utils.R#L1&#34;&gt;here&lt;/a&gt;. Let’s dig into what this function does a little, but first we will define a temporary function to show by example.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;dummy_select &amp;lt;- function(...) {
  deparse_dots(...)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now of course in the real &lt;code&gt;select()&lt;/code&gt; function, &lt;code&gt;select()&lt;/code&gt; takes both data (passed to &lt;code&gt;.data&lt;/code&gt;) and column names (passed to &lt;code&gt;...&lt;/code&gt;) as inputs and then returns a subset of the data object containing only those columns. In our temporary function, we are just interested in the evaluation of the column names. So let’s try it out.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;dummy_select(x, y)
# [1] &amp;quot;x&amp;quot; &amp;quot;y&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here we passed two objects, &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; which are intended to represent our column names. These objects are in fact symbols which we would expect to be evaluated, but they weren’t; they are instead turned into character strings. This is thanks to the &lt;code&gt;deparse()&lt;/code&gt; and &lt;code&gt;substitute()&lt;/code&gt; combination. &lt;code&gt;deparse_dots()&lt;/code&gt; first uses &lt;code&gt;substitute()&lt;/code&gt; to return the unevaluated expression (in our case &lt;code&gt;...()&lt;/code&gt;) and substitutes any variables bound in the environment (here &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;). &lt;code&gt;deparse_dots()&lt;/code&gt; then loops over each of these inputs and deparses them. From the help page, &lt;code&gt;?deparse&lt;/code&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Turn unevaluated expressions into character strings.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So now we have our function column inputs as character strings. This is a good start as we can now match on those character strings with the column names of our data (&lt;code&gt;match(deparse_dots(...), colnames(.data))&lt;/code&gt;) to get the integer column positions of &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;. But what if the user inputs, for example, an integer?&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;dummy_select(1, 3, 5)
# [1] &amp;quot;1&amp;quot; &amp;quot;3&amp;quot; &amp;quot;5&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This now poses a problem. Does the user here mean that they want the first, third and fifth columns returned? Or do they mean that there are columns within their &lt;code&gt;data.frame&lt;/code&gt; called “1”, “3” and “5” - which aren’t necessarily in the first, third and fifth positions - and those are the columns they would like? So the problem with this approach is that when everything is converted to characters, it is almost impossible to know whether the user input to the function is a column name, a column integer position or a function like a &lt;a href=&#34;https://nathaneastwood.github.io/2020/04/13/poorman-select-helpers-bug-fixes-and-tests-tests-tests/&#34;&gt;select helper&lt;/a&gt;, with any degree of certainty. The function has to &lt;code&gt;try()&lt;/code&gt; certain things by making certain assumptions and of course making an assumption makes…well, you’ve heard the saying.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;the-selectificator-2000&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;The Selectificator 2000&lt;/h1&gt;
&lt;p&gt;This is where the upgrades to the &lt;code&gt;poorman::select()&lt;/code&gt; function come in. As a user I want to be able to pass integers, numerics, character strings, symbols and even functions to be interpreted by the &lt;code&gt;select()&lt;/code&gt; function correctly and return the columns I desire. This is where the next line of code - which is absolutely brilliant - comes in.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;eval(substitute(alist(...)))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let’s break this function down and see what it does. We will work with a function and build it up bit by bit.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;dummy_select &amp;lt;- function(...) {
  alist(...)
}
dummy_select(x, y)
# [[1]]
# ...&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ok, not so exciting, right? What about if we wrap this in substitute?&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;dummy_select &amp;lt;- function(...) {
  substitute(alist(...))
}
dummy_select(x, y)
# alist(x, y)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can see that we have managed to pass in our inputs but they seem to be wrapped in an unevaluated call to &lt;code&gt;alist()&lt;/code&gt;, so let’s try and evaluate it.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;dummy_select &amp;lt;- function(...) {
  eval(substitute(alist(...)))
}
dummy_select(x, y)
# [[1]]
# x
# 
# [[2]]
# y&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Perfect! Now we have our unevaluated function inputs stored in a list. But what is so great about that? Well, let’s take a look at the structure of this output.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;str(dummy_select(x, y))
# List of 2
#  $ : symbol x
#  $ : symbol y&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So we can see that our inputs have been stored as their appropriate class; symbols! As a matter of fact, this occurs no matter what we use as our inputs.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;str(dummy_select(1L, 2, &amp;quot;x&amp;quot;, y, starts_with(&amp;quot;R&amp;quot;)))
# List of 5
#  $ : int 1
#  $ : num 2
#  $ : chr &amp;quot;x&amp;quot;
#  $ : symbol y
#  $ : language starts_with(&amp;quot;R&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is fantastic. What this means is that we can now define functionality that can handle each of the separate types we typically expect being used in a call to &lt;code&gt;select()&lt;/code&gt;. All of this magic is owed to the &lt;code&gt;alist()&lt;/code&gt; function, let’s take a look at the documentation.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;alist&lt;/code&gt; handles its arguments as if they described function arguments. So the values are not evaluated, and tagged arguments with no value are allowed whereas &lt;code&gt;list&lt;/code&gt; simply ignores them.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So if we had used the &lt;code&gt;list()&lt;/code&gt; function, it would have attempted to evaluate our inputs to the &lt;code&gt;dummy_select()&lt;/code&gt; function whereas &lt;code&gt;alist()&lt;/code&gt; does not - it stores them as unevaluated objects.&lt;/p&gt;
&lt;p&gt;Now, this starts to get really interesting when we start to take a look at the &lt;code&gt;language&lt;/code&gt; inputs. When using &lt;code&gt;dplyr::select()&lt;/code&gt;, the user is able to select columns in a number of ways. Let’s take a look at some of them and what the structure of those look like.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;str(dummy_select(!w, x:y, -z))
# List of 3
#  $ : language !w
#  $ : language x:y
#  $ : language -z&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So selecting columns through the use of an exclamation mark (negation), a colon or a minus sign actually gives us a &lt;code&gt;language&lt;/code&gt; object. Ok, so what? What is so special about this? Well what makes this so useful to us is how we can interact with the objects. We can actually access parts of the &lt;code&gt;language&lt;/code&gt; object, much in the same way we do with a &lt;code&gt;list()&lt;/code&gt;. Let’s take a look.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;obj &amp;lt;- dummy_select(x:y)
obj[[1]][1]
# `:`()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So operators are actually functions. In fact, in R, everything is an object and we interact with those objects using functions, so this makes sense. Let’s look a bit deeper into this object.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;obj[[1]][[1]]
# `:`
obj[[1]][[2]]
# x
obj[[1]][[3]]
# y&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So our function input, &lt;code&gt;x:y&lt;/code&gt;, can be broken down into it’s individual components. We know that the components are made up of the colon function as well as &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;, but what is the structure of these final two components?&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;str(obj[[1]][[2]])
#  symbol x
str(obj[[1]][[3]])
#  symbol y&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;They are symbols! So now we can handle these much in the same way as we did with the symbol inputs in the first instance, because remember, just passing &lt;code&gt;x&lt;/code&gt; or &lt;code&gt;y&lt;/code&gt; to our &lt;code&gt;dummy_select()&lt;/code&gt; function returned a symbol.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;str(dummy_select(x, y))
# List of 2
#  $ : symbol x
#  $ : symbol y&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So there you have it! This is how you, as the user, are now able to perform &lt;code&gt;select()&lt;/code&gt; calls with &lt;code&gt;{poorman}&lt;/code&gt; like this:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(poorman, warn.conflicts = FALSE)
mtcars %&amp;gt;%
  select(drat, mpg:hp, starts_with(&amp;quot;g&amp;quot;), everything()) %&amp;gt;%
  head()
#                   drat  mpg cyl disp  hp gear    wt  qsec vs am carb
# Mazda RX4         3.90 21.0   6  160 110    4 2.620 16.46  0  1    4
# Mazda RX4 Wag     3.90 21.0   6  160 110    4 2.875 17.02  0  1    4
# Datsun 710        3.85 22.8   4  108  93    4 2.320 18.61  1  1    1
# Hornet 4 Drive    3.08 21.4   6  258 110    3 3.215 19.44  1  0    1
# Hornet Sportabout 3.15 18.7   8  360 175    3 3.440 17.02  0  0    2
# Valiant           2.76 18.1   6  225 105    3 3.460 20.22  1  0    1&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;This post has taken a look at two separate non-standard evaluation approaches - using nothing but &lt;code&gt;{base}&lt;/code&gt; - deployed within the &lt;code&gt;{poorman}&lt;/code&gt; package. We have seen how to break down &lt;code&gt;language&lt;/code&gt; objects to pick out key pieces of information from them. We also saw how to determine the object types of function inputs and why this is important to consider. In particular, this showed how I was able to transform the &lt;code&gt;select()&lt;/code&gt; function into the omega selectificator function…of doom.&lt;/p&gt;
&lt;p&gt;As this blog post is quite long, I haven’t gone into any further details of the internals of &lt;code&gt;{poorman}&lt;/code&gt; however if you are interested in taking a closer look at how I handle the different input types, you can see the code on the relevant &lt;code&gt;{poorman}&lt;/code&gt; &lt;a href=&#34;https://github.com/nathaneastwood/poorman/blob/master/R/select_positions.R&#34;&gt;GitHub page&lt;/a&gt;. &lt;code&gt;{poorman}&lt;/code&gt; is still a work in progress but as you can see, it already has a lot of functionality you know and love from &lt;code&gt;{dplyr}&lt;/code&gt; so if you are working on a new project and don’t want to have to deal with dependency management, especially if you are sharing work with colleagues, why not give &lt;code&gt;{poorman}&lt;/code&gt; a try?&lt;/p&gt;
&lt;p&gt;If you’d like to show your support for &lt;code&gt;{poorman}&lt;/code&gt;, please consider giving the package a &lt;a href=&#34;https://github.com/nathaneastwood/poorman/stargazers&#34;&gt;Star on Github&lt;/a&gt; as it gives me that boost of dopamine needed to continue development.&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>poorman: Select helpers, bug fixes and tests, tests, tests!</title>
      <link>/2020/04/13/poorman-select-helpers-bug-fixes-and-tests-tests-tests/</link>
      <pubDate>Mon, 13 Apr 2020 20:12:00 -0500</pubDate>
      
      <guid>/2020/04/13/poorman-select-helpers-bug-fixes-and-tests-tests-tests/</guid>
      <description>
&lt;script src=&#34;/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;introduction&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Hello all and welcome to another edition of the &lt;code&gt;poorman&lt;/code&gt; series of blog posts. In this series I am discussing my progress in writing a &lt;code&gt;base&lt;/code&gt; R equivalent of &lt;code&gt;dplyr&lt;/code&gt;. What’s nice about this series is that if you’re not into &lt;code&gt;poorman&lt;/code&gt; and would prefer just to use &lt;code&gt;dplyr&lt;/code&gt;, then that’s absolutely OK! By highlighting &lt;code&gt;poorman&lt;/code&gt; functionality, this series of blog posts simultaneously highlights &lt;code&gt;dplyr&lt;/code&gt; functionality too!&lt;/p&gt;
&lt;p&gt;Today I want to showcase some column selection helper features from the &lt;code&gt;tidyselect&lt;/code&gt; package - often used in conjunction with &lt;code&gt;dplyr&lt;/code&gt; - which I have finished now replicated within &lt;code&gt;poorman&lt;/code&gt;, of course using &lt;code&gt;base&lt;/code&gt; only. I’ll also discuss a little bit about what is happening in the background of &lt;code&gt;poorman&lt;/code&gt;’s development with regards to testing.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;select-helpers&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Select Helpers&lt;/h1&gt;
&lt;p&gt;The first official release version of &lt;code&gt;poorman&lt;/code&gt; (v 0.1.9) was the first version that I considered to contain all of the “core” functionality of &lt;code&gt;dplyr&lt;/code&gt;; everything from &lt;code&gt;select()&lt;/code&gt; to &lt;code&gt;group_by()&lt;/code&gt; and &lt;code&gt;summarise()&lt;/code&gt;. Now that that functionality is nailed down, it gives me time to focus of some of the smaller features of &lt;code&gt;dplyr&lt;/code&gt; and the wider &lt;code&gt;tidyverse&lt;/code&gt; and so over the last couple of weeks I have been working on adding the &lt;code&gt;tidyselect::select_helpers&lt;/code&gt; to &lt;code&gt;poorman&lt;/code&gt;. For those that are unaware, &lt;code&gt;select_helpers&lt;/code&gt; are a collection of functions that help the user to select variables based on their names. For example you may wish to select all columns which start with a certain prefix or maybe select columns matching a particular regular expression. Let’s take a look at some examples.&lt;/p&gt;
&lt;div id=&#34;selecting-columns-based-on-partial-column-names&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Selecting Columns Based On Partial Column Names&lt;/h2&gt;
&lt;p&gt;If your data contain lots of columns whose names share a similar structure, you can use partial matching by adding &lt;code&gt;starts_with()&lt;/code&gt;, &lt;code&gt;ends_with()&lt;/code&gt; or &lt;code&gt;contains()&lt;/code&gt; in your &lt;code&gt;select()&lt;/code&gt;/&lt;code&gt;relocate()&lt;/code&gt; statement.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(poorman, warn.conflicts = FALSE)
iris %&amp;gt;% select(starts_with(&amp;quot;Petal&amp;quot;), ends_with(&amp;quot;Width&amp;quot;)) %&amp;gt;% head()
#   Petal.Length Petal.Width Sepal.Width
# 1          1.4         0.2         3.5
# 2          1.4         0.2         3.0
# 3          1.3         0.2         3.2
# 4          1.5         0.2         3.1
# 5          1.4         0.2         3.6
# 6          1.7         0.4         3.9&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;reordering-columns&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Reordering Columns&lt;/h2&gt;
&lt;p&gt;The columns of the &lt;code&gt;iris&lt;/code&gt; dataset come in the following order.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;colnames(iris)
# [1] &amp;quot;Sepal.Length&amp;quot; &amp;quot;Sepal.Width&amp;quot;  &amp;quot;Petal.Length&amp;quot; &amp;quot;Petal.Width&amp;quot;  &amp;quot;Species&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But what if we wanted all of the “Width” columns at the start of this &lt;code&gt;data.frame&lt;/code&gt;? There are a couple of ways in which we can achieve this. Firstly, we can use &lt;code&gt;select()&lt;/code&gt; in combination with the select helper &lt;code&gt;everything()&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;iris %&amp;gt;% select(&amp;quot;Petal.Width&amp;quot;, &amp;quot;Sepal.Width&amp;quot;, everything()) %&amp;gt;% head()
#   Petal.Width Sepal.Width Sepal.Length Petal.Length Species
# 1         0.2         3.5          5.1          1.4  setosa
# 2         0.2         3.0          4.9          1.4  setosa
# 3         0.2         3.2          4.7          1.3  setosa
# 4         0.2         3.1          4.6          1.5  setosa
# 5         0.2         3.6          5.0          1.4  setosa
# 6         0.4         3.9          5.4          1.7  setosa&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;poorman&lt;/code&gt; here first selects the columns “Petal.Width” and “Sepal.Width” before selecting everything else. This is great, but if your data contain a lot of columns containing “Width” then you will have to write out a lot of column names. Well this is where we can use &lt;code&gt;relocate()&lt;/code&gt; and the select helper &lt;code&gt;contains()&lt;/code&gt; to move those columns to the start of &lt;code&gt;iris&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;iris %&amp;gt;% relocate(contains(&amp;quot;Width&amp;quot;)) %&amp;gt;% head()
#   Sepal.Width Petal.Width Sepal.Length Petal.Length Species
# 1         3.5         0.2          5.1          1.4  setosa
# 2         3.0         0.2          4.9          1.4  setosa
# 3         3.2         0.2          4.7          1.3  setosa
# 4         3.1         0.2          4.6          1.5  setosa
# 5         3.6         0.2          5.0          1.4  setosa
# 6         3.9         0.4          5.4          1.7  setosa&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By default, &lt;code&gt;relocate()&lt;/code&gt; will move all selected columns to the start of the &lt;code&gt;data.frame&lt;/code&gt;. You can adjust this behaviour with the &lt;code&gt;.before&lt;/code&gt; and &lt;code&gt;.after&lt;/code&gt; parameters. Let’s move the “Petal” columns to appear after the “Species” column.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;iris %&amp;gt;% relocate(contains(&amp;quot;Petal&amp;quot;), .after = Species) %&amp;gt;% head()
#   Sepal.Length Sepal.Width Species Petal.Length Petal.Width
# 1          5.1         3.5  setosa          1.4         0.2
# 2          4.9         3.0  setosa          1.4         0.2
# 3          4.7         3.2  setosa          1.3         0.2
# 4          4.6         3.1  setosa          1.5         0.2
# 5          5.0         3.6  setosa          1.4         0.2
# 6          5.4         3.9  setosa          1.7         0.4&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;select-columns-using-a-regular-expression&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Select Columns Using a Regular Expression&lt;/h2&gt;
&lt;p&gt;The previous helper functions work with exact pattern matches. Let’s say you have similar patterns within your column names that are not quite the same, you can use regular expressions with the &lt;code&gt;matches()&lt;/code&gt; helper function to identify them. Here I will use the &lt;code&gt;mtcars&lt;/code&gt; dataset and look to extract all columns which start with a “w” or a “d” and end with a “t”.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars %&amp;gt;% select(matches(&amp;quot;^[wd].*[t]$&amp;quot;)) %&amp;gt;% head()
#                   drat    wt
# Mazda RX4         3.90 2.620
# Mazda RX4 Wag     3.90 2.875
# Datsun 710        3.85 2.320
# Hornet 4 Drive    3.08 3.215
# Hornet Sportabout 3.15 3.440
# Valiant           2.76 3.460&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;the-select-helper-list&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The Select Helper List&lt;/h2&gt;
&lt;p&gt;We have seen a few examples of select helpers now available in &lt;code&gt;poorman&lt;/code&gt;. There are more, however, and the following list details each of them. Remember that these functions can be used to help users &lt;code&gt;select()&lt;/code&gt; and &lt;code&gt;relocate()&lt;/code&gt; columns within &lt;code&gt;data.frame&lt;/code&gt;s.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;starts_with()&lt;/code&gt;: Starts with a prefix.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ends_with()&lt;/code&gt;: Ends with a suffix.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;contains()&lt;/code&gt;: Contains a literal string.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;matches()&lt;/code&gt;: Matches a regular expression.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;num_range()&lt;/code&gt;: Matches a numerical range like &lt;code&gt;x01&lt;/code&gt;, &lt;code&gt;x02&lt;/code&gt;, &lt;code&gt;x03&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;all_of()&lt;/code&gt;: Matches variable names in a character vector. All names must be present, otherwise an out-of-bounds error is thrown.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;any_of()&lt;/code&gt;: Same as &lt;code&gt;all_of()&lt;/code&gt;, except that no error is thrown for names that don’t exist.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;everything()&lt;/code&gt;: Matches all variables.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;last_col()&lt;/code&gt;: Select last variable, possibly with an offset.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;docker&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Docker&lt;/h1&gt;
&lt;p&gt;There was a request on Twitter to put together a Docker image for &lt;code&gt;poorman&lt;/code&gt;. This has now been done and can be seen on &lt;a href=&#34;https://hub.docker.com/repository/docker/nathaneastwood/poorman&#34;&gt;Dockerhub&lt;/a&gt;. This means if you have Docker installed, you can run a containerised version of &lt;code&gt;poorman&lt;/code&gt; easily with the following line of code.&lt;/p&gt;
&lt;pre class=&#34;bash&#34;&gt;&lt;code&gt;docker run --rm -it nathaneastwood/poorman&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;test-test-test&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Test, Test, Test!&lt;/h1&gt;
&lt;p&gt;Since the &lt;a href=&#34;https://nathaneastwood.github.io/2020/04/01/poorman-first-release-of-a-base-r-dplyr-clone/&#34;&gt;last release&lt;/a&gt; of &lt;code&gt;poorman&lt;/code&gt; (v 0.1.9) to CRAN, I have been working on a few bugs that I and other users of the package had identified. I’m happy to say that these have now been squashed and the &lt;a href=&#34;https://github.com/nathaneastwood/poorman/issues&#34;&gt;issues list&lt;/a&gt; is looking very empty. As a brief overview, the following problems are now fixed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;mutate()&lt;/code&gt; column creations are immediately available, e.g. &lt;code&gt;mtcars %&amp;gt;% mutate(mpg2 = mpg * 2, mpg4 = mpg2 * 2)&lt;/code&gt; will create columns named &lt;code&gt;mpg2&lt;/code&gt; and &lt;code&gt;mpg4&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;group_by()&lt;/code&gt; groups now persist in selections, e.g. &lt;code&gt;mtcars %&amp;gt;% group_by(am) %&amp;gt;% select(mpg)&lt;/code&gt; will return &lt;code&gt;am&lt;/code&gt; and &lt;code&gt;mpg&lt;/code&gt; columns&lt;/li&gt;
&lt;li&gt;&lt;code&gt;slice()&lt;/code&gt; now duplicates rows, e.g. &lt;code&gt;mtcars %&amp;gt;% slice(2, 2, 2)&lt;/code&gt; will return row 2 three times&lt;/li&gt;
&lt;li&gt;&lt;code&gt;summarize()&lt;/code&gt; is now exported&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;dplyr&lt;/code&gt; is a very well known and extremely well developed package. In order for &lt;code&gt;poorman&lt;/code&gt; to have any credibility, it needs to work correctly. Therefore a large amount of effort and energy has gone into testing &lt;code&gt;poorman&lt;/code&gt; to ensure it produces the results one would expect. Since adding all of the new features and bug fixes described in this blog, &lt;code&gt;poorman&lt;/code&gt; has surpassed 100 tests!&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;tinytest::test_all()                                    
# Running test_arrange.R................    5 tests OK
# Running test_filter.R.................    6 tests OK
# Running test_groups.R.................    5 tests OK
# Running test_joins_filter.R...........    4 tests OK
# Running test_joins.R..................    7 tests OK
# Running test_mutate.R.................    6 tests OK
# Running test_pull.R...................    6 tests OK
# Running test_relocate.R...............    6 tests OK
# Running test_rename.R.................    4 tests OK
# Running test_rownames.R...............    2 tests OK
# Running test_select_helpers.R.........   25 tests OK
# Running test_select.R.................   13 tests OK
# Running test_slice.R..................    5 tests OK
# Running test_summarise.R..............    6 tests OK
# Running test_transmute.R..............    3 tests OK
# Running test_utils.R..................    1 tests OK
# [1] &amp;quot;All ok, 104 results&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This also means that the package coverage is extremely high.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;covr::package_coverage()                                                                                        #
# poorman Coverage: 97.87%
# R/utils.R: 80.00%
# R/group.R: 90.91%
# R/joins.R: 92.86%
# R/arrange.R: 100.00%
# R/filter.R: 100.00%
# R/init.R: 100.00%
# R/joins_filtering.R: 100.00%
# R/mutate.R: 100.00%
# R/pipe.R: 100.00%
# R/pull.R: 100.00%
# R/relocate.R: 100.00%
# R/rename.R: 100.00%
# R/rownames.R: 100.00%
# R/select_helpers.R: 100.00%
# R/select.R: 100.00%
# R/slice.R: 100.00%
# R/summarise.R: 100.00%
# R/transmute.R: 100.00%&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I hope this gives users of &lt;code&gt;poorman&lt;/code&gt; that extra confidence when using the package. I have now submitted this updated version of &lt;code&gt;poorman&lt;/code&gt; to CRAN and I am just waiting on their feedback so hopefully in the coming days it will be available. Watch this space!&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>poorman: First Release of a base R dplyr Clone</title>
      <link>/2020/04/01/poorman-first-release-of-a-base-r-dplyr-clone/</link>
      <pubDate>Wed, 01 Apr 2020 20:12:00 -0500</pubDate>
      
      <guid>/2020/04/01/poorman-first-release-of-a-base-r-dplyr-clone/</guid>
      <description>
&lt;script src=&#34;/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;introduction&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;The first official release of &lt;code&gt;poorman&lt;/code&gt; (v 0.1.9) is &lt;a href=&#34;https://cran.r-project.org/web/packages/poorman/index.html&#34;&gt;now on CRAN&lt;/a&gt;! You can now install &lt;code&gt;poorman&lt;/code&gt; directly from CRAN with the following code:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;install.packages(&amp;quot;poorman&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this blog post I want to address some common questions that I have received since I started writing the package.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;what-is-poorman&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;What is &lt;code&gt;poorman&lt;/code&gt;?&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;poorman&lt;/code&gt; is a package that unapologetically attempts to recreate the &lt;code&gt;dplyr&lt;/code&gt; API in a dependency free way using only &lt;code&gt;base&lt;/code&gt; R. &lt;code&gt;poorman&lt;/code&gt; is still under development and doesn’t have all of &lt;code&gt;dplyr&lt;/code&gt;’s functionality but what I would consider the “core” functionality is included. The idea behind &lt;code&gt;poorman&lt;/code&gt; is that a user should be able to take their &lt;code&gt;dplyr&lt;/code&gt; based script and run it using &lt;code&gt;poorman&lt;/code&gt; without any hiccups.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;so-what-does-poorman-include&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;So what does &lt;code&gt;poorman&lt;/code&gt; include?&lt;/h1&gt;
&lt;p&gt;In this first official release, &lt;code&gt;poorman&lt;/code&gt; includes copies of the key &lt;code&gt;dplyr&lt;/code&gt; functions.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;select(), rename(), pull(), relocate(), mutate(), transmute(), arrange()
filter(), slice()
summarise() / summarize()
group_by(), ungroup()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;poorman&lt;/code&gt; also includes the join functionality.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;inner_join(), left_join(), right_join(), full_join()
anti_join(), semi_join()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally &lt;code&gt;poorman&lt;/code&gt; also includes its own version of the pipe so you do not need to load or install &lt;code&gt;magrittr&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;%&amp;gt;%&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;More functionality is being developed and will be added in time.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;why-develop-poorman&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Why develop &lt;code&gt;poorman&lt;/code&gt;?&lt;/h1&gt;
&lt;p&gt;This is probably the most common question; why bother developing &lt;code&gt;poorman&lt;/code&gt; when &lt;code&gt;dplyr&lt;/code&gt; already exists. Well there are actually several reasons why I decided to develop it. The most important reason to me though is quite simply because I can. &lt;code&gt;poorman&lt;/code&gt; started out as a personal challenge and a bit of fun. Also as a freelance R developer, it is good to build up my portfolio of open source code that I can show to potential clients.&lt;/p&gt;
&lt;p&gt;Another reason for developing &lt;code&gt;poorman&lt;/code&gt; is I wanted to challenge a common misconception that &lt;code&gt;base&lt;/code&gt; R is not as powerful, or as good, or as useful as &lt;code&gt;dplyr&lt;/code&gt;. Too often I see and hear comments belittling &lt;code&gt;base&lt;/code&gt; R and as a user of the language for over 10 years now - well before the inception of &lt;code&gt;dplyr&lt;/code&gt; - I find this idea very worrying. &lt;code&gt;poorman&lt;/code&gt;’s package start up message is quite poignant in this regard.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I’d seen my father. He was a poor man, and I watched him do astonishing things. - Sidney Poitier&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Finally, I have a natural joy of teaching. Writing &lt;code&gt;poorman&lt;/code&gt; gives me a platform to hopefully show useRs two key aspects of R programming in &lt;code&gt;base&lt;/code&gt;; common data manipulation tasks; and non-standard evaulation.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;but-why-not-just-use-dplyr&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;But why not just use &lt;code&gt;dplyr&lt;/code&gt;?&lt;/h1&gt;
&lt;p&gt;Let’s be honest, the &lt;code&gt;tidyverse&lt;/code&gt; is a fantastic set of packages which have transformed the face of data analysis in R, and &lt;code&gt;dplyr&lt;/code&gt; is arguably one of the most important packages within the &lt;code&gt;tidyverse&lt;/code&gt;. The API is in my opinion very easy to learn and use.&lt;/p&gt;
&lt;p&gt;Being a part of the &lt;code&gt;tidyverse&lt;/code&gt;, however, means that &lt;code&gt;dplyr&lt;/code&gt; comes with a large number of dependencies that users must also install which is often seen as a disadvantage to using the &lt;code&gt;tidyverse&lt;/code&gt;. Disadvantages of dependencies have been &lt;a href=&#34;http://dirk.eddelbuettel.com/blog/2018/02/28/#017_dependencies&#34;&gt;written about&lt;/a&gt; before and so I won’t go into detail here. However what I will say is that the user may not have a need for additional parts of the &lt;code&gt;tidyverse&lt;/code&gt; and so may not wish to have to install multiple packages to use one or two functions.&lt;/p&gt;
&lt;p&gt;Some of these dependencies are very useful of course, allowing expansion into other areas such as accessing Spark instances and databases using the same API the user already knows. This is great and if you are using these additional tools then I absolutely recommend that you choose &lt;code&gt;dplyr&lt;/code&gt; over &lt;code&gt;poorman&lt;/code&gt;. However if you don’t need the extra dependencies and functionality that comes with the wider &lt;code&gt;tidyverse&lt;/code&gt; then maybe consider giving the lightweight &lt;code&gt;poorman&lt;/code&gt; a go.&lt;/p&gt;
&lt;p&gt;Finally a point on installation times, &lt;code&gt;poorman&lt;/code&gt; takes roughly six seconds to install. If you’ve ever had to install or upgrade &lt;code&gt;dplyr&lt;/code&gt; or the &lt;code&gt;tidyverse&lt;/code&gt;, you’ll recognise that this is very fast.&lt;/p&gt;
&lt;center&gt;
&lt;img src=&#34;/img/poorman_installation.gif&#34; /&gt;
&lt;/center&gt;
&lt;/div&gt;
&lt;div id=&#34;why-the-name-poorman&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Why the name &lt;code&gt;poorman&lt;/code&gt;?&lt;/h1&gt;
&lt;p&gt;As I have already mentioned, I have seen comments in the past pertaining to R’s worthlessness without the &lt;code&gt;tidyverse&lt;/code&gt; and so the name &lt;code&gt;poorman&lt;/code&gt; is a subtle play on the the idea that you must be a “poor man” if you use &lt;code&gt;base&lt;/code&gt;. The irony of course is that I have managed to recreate - quite easily - the key parts of the &lt;code&gt;dplyr&lt;/code&gt; API using only &lt;code&gt;base&lt;/code&gt; R.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;why-not-use-data.table-for-the-backend&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Why not use &lt;code&gt;data.table&lt;/code&gt; for the backend?&lt;/h1&gt;
&lt;p&gt;Because I wanted to build something that was completely dependency free and adding &lt;code&gt;data.table&lt;/code&gt; as an &lt;code&gt;Import&lt;/code&gt; adds a dependency.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;but-doesnt-poorman-have-dependencies&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;But doesn’t &lt;code&gt;poorman&lt;/code&gt; have dependencies?&lt;/h1&gt;
&lt;p&gt;To answer this, we need to define what we mean by “dependency free”. &lt;code&gt;poorman&lt;/code&gt; does have some dependencies but they are for development purposes only and are therefore listed in the &lt;code&gt;Suggests&lt;/code&gt; part of the &lt;code&gt;DESCRIPTION&lt;/code&gt; file. Thus when a user installs the package, these dependencies are only ever installed if they are explicitly requested. However, &lt;code&gt;poorman&lt;/code&gt; doesn’t have any dependencies that users of the package need to install in order to use its functionality. I use these dependency packages to help me develop more easily. Therefore &lt;code&gt;poorman&lt;/code&gt; isn’t a truly “dependency free” like &lt;code&gt;data.table&lt;/code&gt; is, but it is dependency free for its intended users.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;So if you find yourself needing a dependency free data manipulation package that follows the &lt;code&gt;dplyr&lt;/code&gt; API with short installation times then give &lt;code&gt;poorman&lt;/code&gt; a try. Equally if you find any issues, please submit an issue to &lt;a href=&#34;https://github.com/nathaneastwood/poorman/issues&#34;&gt;&lt;code&gt;GitHub&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>poorman: Replicating dplyr&#39;s Join and Filter Join Functions with base R</title>
      <link>/2020/03/08/poorman-replicating-dplyrs-join-and-filter-join-functions-with-base-r/</link>
      <pubDate>Sun, 08 Mar 2020 20:12:00 -0500</pubDate>
      
      <guid>/2020/03/08/poorman-replicating-dplyrs-join-and-filter-join-functions-with-base-r/</guid>
      <description>


&lt;div id=&#34;introduction&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;In my &lt;a href=&#34;https://nathaneastwood.github.io/2020/02/27/building-a-base-dplyr-with-primitives-grouped-operations-pipes-and-more/&#34;&gt;last post&lt;/a&gt; I discussed performing split-apply-combine operations on R &lt;code&gt;data.frame&lt;/code&gt;s and how this functionality was used within &lt;a href=&#34;https://github.com/nathaneastwood/poorman&#34;&gt;&lt;code&gt;poorman&lt;/code&gt;&lt;/a&gt; - a &lt;code&gt;base&lt;/code&gt; R replica of &lt;code&gt;dplyr&lt;/code&gt;. In this post I’d like to talk about replicating &lt;code&gt;dplyr&lt;/code&gt;’s join and filter join functionality, again using nothing but &lt;code&gt;base&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;joins&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Joins&lt;/h1&gt;
&lt;p&gt;First of all, let’s set up some data to use for our examples. Here I create two &lt;code&gt;data.frame&lt;/code&gt;s; one containing heights associated with names and IDs; the second containing weights also associated with some names and IDs. Some of these ID and name combinations are common to both tables (e.g. &lt;code&gt;c(&#34;id&#34; = 5, &#34;name&#34; = &#34;C&#34;)&lt;/code&gt;) but other IDs are unique to one table or the other (e.g. &lt;code&gt;c(&#34;id&#34; = 1, &#34;name&#34; = &#34;A&#34;)&lt;/code&gt;).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that sometimes a list of elements (here name and ID) are somtimes referred to as a tuple.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;table1 &amp;lt;- data.frame(
  id = c(1, 3, 5, 7, 9),
  name = LETTERS[1:5],
  height = c(1, 2, 2, 2, 2),
  stringsAsFactors = FALSE
)
table1
#   id name height
# 1  1    A      1
# 2  3    B      2
# 3  5    C      2
# 4  7    D      2
# 5  9    E      2
table2 &amp;lt;- data.frame(
  id = c(2, 4, 5, 7),
  name = LETTERS[1:4],
  weight = c(2, 3, 4, 5),
  stringsAsFactors = FALSE
)
table2
#   id name weight
# 1  2    A      2
# 2  4    B      3
# 3  5    C      4
# 4  7    D      5&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When working with data such as this, we may wish to join these two tables together such that we can more easily use data from both. In &lt;code&gt;base&lt;/code&gt;, the function we use for joining tables together is called &lt;code&gt;merge()&lt;/code&gt;. We will see how we can use this one function to perform inner, left, right and full joins.&lt;/p&gt;
&lt;div id=&#34;inner-join&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Inner Join&lt;/h2&gt;
&lt;p&gt;An inner join selects records that have matching values in both tables within the columns we are joining by, returning all columns. For &lt;code&gt;table1&lt;/code&gt; and &lt;code&gt;table2&lt;/code&gt;, we will be joining the tables by &lt;code&gt;&#34;id&#34;&lt;/code&gt; and &lt;code&gt;&#34;name&#34;&lt;/code&gt; since these are the common columns between both tables.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that depending on your circumstance you may not wish to join on all common columns. For example you may have two tables that have columns with the same name but actually contain different data.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;When we perform the inner join therefore, we will expect a &lt;code&gt;data.frame&lt;/code&gt; containing the records &lt;code&gt;c(&#34;id&#34; = 5, &#34;name&#34; = &#34;C&#34;)&lt;/code&gt; and &lt;code&gt;c(&#34;id&#34; = 7, &#34;name&#34; = &#34;D&#34;)&lt;/code&gt; since these records exist in both tables.&lt;/p&gt;
&lt;p&gt;To perform an inner join, we use the &lt;code&gt;merge()&lt;/code&gt; function with no additional parameters, giving the two tables to merge.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;merge(x = table1, y = table2)
#   id name height weight
# 1  5    C      2      4
# 2  7    D      2      5&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When performing a join, we typically specify which columns we would like to join on. &lt;code&gt;merge()&lt;/code&gt; is helpful in that it works out the common columns between the datasets with the following command.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;by &amp;lt;- intersect(names(table1), names(table2))
by
# [1] &amp;quot;id&amp;quot;   &amp;quot;name&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we wanted, we could pass the column names explicitly.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;merge(x = table1, y = table2, by = c(&amp;quot;id&amp;quot;, &amp;quot;name&amp;quot;))
#   id name height weight
# 1  5    C      2      4
# 2  7    D      2      5&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In &lt;code&gt;poorman&lt;/code&gt;, we can use the &lt;code&gt;inner_join()&lt;/code&gt; function to perform this type of join.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;table1 %&amp;gt;% inner_join(table2)
# Joining, by = c(&amp;quot;id&amp;quot;, &amp;quot;name&amp;quot;)
#   id name height weight
# 1  5    C      2      4
# 2  7    D      2      5&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;left-join&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Left Join&lt;/h2&gt;
&lt;p&gt;A left join will include all rows from &lt;code&gt;table1&lt;/code&gt; regardless of whether or not there is a matching record in &lt;code&gt;table2&lt;/code&gt;. For those records which do not have a match, the left join will leave the cells as &lt;code&gt;NA&lt;/code&gt; values. In &lt;code&gt;base&lt;/code&gt;, we perform this type of join with the &lt;code&gt;merge()&lt;/code&gt; function, specifying &lt;code&gt;all.x = TRUE&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;merge(x = table1, y = table2, all.x = TRUE)
#   id name height weight
# 1  1    A      1     NA
# 2  3    B      2     NA
# 3  5    C      2      4
# 4  7    D      2      5
# 5  9    E      2     NA&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In &lt;code&gt;poorman&lt;/code&gt;, this type of join can be performed with &lt;code&gt;left_join()&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;table1 %&amp;gt;% left_join(table2)
# Joining, by = c(&amp;quot;id&amp;quot;, &amp;quot;name&amp;quot;)
#   id name height weight
# 1  1    A      1     NA
# 2  3    B      2     NA
# 3  5    C      2      4
# 4  7    D      2      5
# 5  9    E      2     NA&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;right-join&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Right Join&lt;/h2&gt;
&lt;p&gt;A right join is the opposite of a left join. Here, the &lt;code&gt;merge()&lt;/code&gt; function returns all rows from &lt;code&gt;table2&lt;/code&gt; and the matched rows from &lt;code&gt;table1&lt;/code&gt;; again filling any blank cells with &lt;code&gt;NA&lt;/code&gt;. This time, we specify &lt;code&gt;all.y = TRUE&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;merge(x = table1, y = table2, all.y = TRUE)
#   id name height weight
# 1  2    A     NA      2
# 2  4    B     NA      3
# 3  5    C      2      4
# 4  7    D      2      5&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In &lt;code&gt;poorman&lt;/code&gt;, this type of join can be performed with, you guessed it, &lt;code&gt;right_join()&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;table1 %&amp;gt;% right_join(table2)
# Joining, by = c(&amp;quot;id&amp;quot;, &amp;quot;name&amp;quot;)
#   id name height weight
# 1  2    A     NA      2
# 2  4    B     NA      3
# 3  5    C      2      4
# 4  7    D      2      5&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;full-join&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Full Join&lt;/h2&gt;
&lt;p&gt;A full join will join together all rows from two tables. Like the left and right joins, any rows that do not contain a match will contain &lt;code&gt;NA&lt;/code&gt; in the cells that are missing. Here we specify &lt;code&gt;all = TRUE&lt;/code&gt; within &lt;code&gt;merge()&lt;/code&gt; to represent a full join.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;merge(x = table1, y = table2, all = TRUE)
#   id name height weight
# 1  1    A      1     NA
# 2  2    A     NA      2
# 3  3    B      2     NA
# 4  4    B     NA      3
# 5  5    C      2      4
# 6  7    D      2      5
# 7  9    E      2     NA&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally &lt;code&gt;poorman&lt;/code&gt; provides &lt;code&gt;full_join()&lt;/code&gt; to do this type of join.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;table1 %&amp;gt;% full_join(table2)
# Joining, by = c(&amp;quot;id&amp;quot;, &amp;quot;name&amp;quot;)
#   id name height weight
# 1  1    A      1     NA
# 2  2    A     NA      2
# 3  3    B      2     NA
# 4  4    B     NA      3
# 5  5    C      2      4
# 6  7    D      2      5
# 7  9    E      2     NA&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;filter-joins&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Filter Joins&lt;/h1&gt;
&lt;p&gt;For filter joins we will look at some slightly different data.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;table1 &amp;lt;- data.frame(
  pupil = rep(1:3, each = 2),
  test = rep(c(&amp;quot;A&amp;quot;, &amp;quot;B&amp;quot;), 3),
  score = c(60, 70, 65, 80, 85, 70),
  stringsAsFactors = FALSE
)
table1
#   pupil test score
# 1     1    A    60
# 2     1    B    70
# 3     2    A    65
# 4     2    B    80
# 5     3    A    85
# 6     3    B    70
table2 &amp;lt;- table1[c(1, 3, 4), ]
table2
#   pupil test score
# 1     1    A    60
# 3     2    A    65
# 4     2    B    80&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;semi-join&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Semi-Join&lt;/h2&gt;
&lt;p&gt;A semi-join is slightly different to the other types of joins we have seen thus far. We describe a semi-join as a “filter join”, since a semi-join returns the rows in &lt;code&gt;table1&lt;/code&gt; where the join column tuples in &lt;code&gt;table1&lt;/code&gt; are also found in &lt;code&gt;table2&lt;/code&gt;. So we still specify the column names that we wish to “join” by (in this example it’s &lt;code&gt;c(&#34;pupil&#34;, &#34;test&#34;)&lt;/code&gt;), which is why this is considered a join but we are actually performing a sort of filter on &lt;code&gt;table1&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;by &amp;lt;- c(&amp;quot;pupil&amp;quot;, &amp;quot;test&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since we are looking for the rows in &lt;code&gt;table1&lt;/code&gt; that are also in &lt;code&gt;table2&lt;/code&gt;, we will be using &lt;code&gt;[.data.frame&lt;/code&gt; to filter &lt;code&gt;table1&lt;/code&gt; by the matching rows. To do this, we will take advantage of &lt;code&gt;base::interaction()&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;interaction(table1[, by])
# [1] 1.A 1.B 2.A 2.B 3.A 3.B
# Levels: 1.A 2.A 3.A 1.B 2.B 3.B&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, what this function does is compute a vector of factor levels which represents the interaction of the given columns. So the number before the &lt;code&gt;.&lt;/code&gt; is the pupil and the letter after the &lt;code&gt;.&lt;/code&gt; is the test they took. If we do this for both tables, we can figure out which levels are &lt;code&gt;%in%&lt;/code&gt; both tables. As we can see below, the results of &lt;code&gt;%in%&lt;/code&gt; returns a logical vector that we can use to filter &lt;code&gt;table1&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;interaction(table2[, by])
# [1] 1.A 2.A 2.B
# Levels: 1.A 2.A 1.B 2.B
rows &amp;lt;- interaction(table1[, by]) %in% interaction(table2[, by])
rows
# [1]  TRUE FALSE  TRUE  TRUE FALSE FALSE&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So here we can see that levels &lt;code&gt;1.A&lt;/code&gt;, &lt;code&gt;2.A&lt;/code&gt; and &lt;code&gt;2.B&lt;/code&gt; appear in both &lt;code&gt;table1&lt;/code&gt; and &lt;code&gt;table2&lt;/code&gt;. So now we can perform our filter.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;table1[rows, ]
#   pupil test score
# 1     1    A    60
# 3     2    A    65
# 4     2    B    80&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Semi-join functionality is afforded by &lt;code&gt;poorman&lt;/code&gt; using the &lt;code&gt;semi_join()&lt;/code&gt; function.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;table1 %&amp;gt;% semi_join(table2)
# Joining, by = c(&amp;quot;pupil&amp;quot;, &amp;quot;test&amp;quot;, &amp;quot;score&amp;quot;)
#   pupil test score
# 1     1    A    60
# 2     2    A    65
# 3     2    B    80&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;anti-join&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Anti-Join&lt;/h2&gt;
&lt;p&gt;An anti-join is slightly different to a semi-join in that it returns all the rows from &lt;code&gt;table1&lt;/code&gt; that &lt;em&gt;do not&lt;/em&gt; appear in &lt;code&gt;table2&lt;/code&gt; when “joining” on the join columns. Using our previously defined &lt;code&gt;rows&lt;/code&gt; variable, we can take the inverse of this logical vector using &lt;code&gt;!&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;rows &amp;lt;- !rows
rows
# [1] FALSE  TRUE FALSE FALSE  TRUE  TRUE
table1[rows, ]
#   pupil test score
# 2     1    B    70
# 5     3    A    85
# 6     3    B    70&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;poorman&lt;/code&gt; provides a copy of anti-join functionality using &lt;code&gt;anti_join()&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;table1 %&amp;gt;% anti_join(table2)
# Joining, by = c(&amp;quot;pupil&amp;quot;, &amp;quot;test&amp;quot;, &amp;quot;score&amp;quot;)
#   pupil test score
# 1     1    B    70
# 2     3    A    85
# 3     3    B    70&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;As we can see, the join and filter join functionality provided by &lt;code&gt;dplyr&lt;/code&gt; is also available in &lt;code&gt;base&lt;/code&gt;, you just need to know the parameter details or how to perform the filters efficiently. For your convenience, these functions are now available in &lt;code&gt;poorman&lt;/code&gt; using the same &lt;code&gt;dplyr&lt;/code&gt; API: &lt;code&gt;inner_join()&lt;/code&gt;, &lt;code&gt;left_join()&lt;/code&gt;, &lt;code&gt;right_join()&lt;/code&gt;, &lt;code&gt;full_join()&lt;/code&gt;, &lt;code&gt;semi_join()&lt;/code&gt; and &lt;code&gt;anti_join()&lt;/code&gt;. See &lt;code&gt;poorman::joins&lt;/code&gt; or &lt;code&gt;?poorman::filter_joins&lt;/code&gt; for more details.&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Building A base dplyr With Primitives: Grouped Operations, Pipes and More!</title>
      <link>/2020/02/27/building-a-base-dplyr-with-primitives-grouped-operations-pipes-and-more/</link>
      <pubDate>Thu, 27 Feb 2020 20:12:00 -0500</pubDate>
      
      <guid>/2020/02/27/building-a-base-dplyr-with-primitives-grouped-operations-pipes-and-more/</guid>
      <description>


&lt;div id=&#34;introduction&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;In my &lt;a href=&#34;https://nathaneastwood.github.io/2020/02/15/building-a-base-dplyr-with-primitives/&#34;&gt;last post&lt;/a&gt; we looked at how we can recreate &lt;code&gt;base&lt;/code&gt; equivalents of the &lt;code&gt;dplyr&lt;/code&gt; functions &lt;code&gt;select()&lt;/code&gt;, &lt;code&gt;filter()&lt;/code&gt;, &lt;code&gt;mutate()&lt;/code&gt; and &lt;code&gt;arrange()&lt;/code&gt;, amongst others. I wrote these functions and presented them in a new package called &lt;a href=&#34;https://github.com/nathaneastwood/poorman&#34;&gt;&lt;code&gt;poorman&lt;/code&gt;&lt;/a&gt;. In this post I will be discussing new functionality that I have since added to &lt;code&gt;poorman&lt;/code&gt; including grouped operations, renaming columns, summarising data and even &lt;code&gt;poorman&lt;/code&gt;’s very own pipe operator!&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;group-by&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Group By&lt;/h1&gt;
&lt;div id=&#34;the-base-way&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The &lt;code&gt;base&lt;/code&gt; Way&lt;/h2&gt;
&lt;p&gt;Typically in the past when I have performed grouped operations using &lt;code&gt;base&lt;/code&gt; I have used the tried and tested split-apply-combine approach. That is, I split the &lt;code&gt;data.frame&lt;/code&gt; on a grouping variable, I apply a function and then I combine the parts back together. Let’s take a look at what I mean using the &lt;code&gt;mtcars&lt;/code&gt; dataset by splitting the data into groups representing each combination of transmission type and number of cylinders (see &lt;code&gt;?datasets::mtcars&lt;/code&gt; for more details about this dataset).&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Split the data into a list of data.frames - one for each group
split &amp;lt;- split(mtcars, list(mtcars$am, mtcars$cyl))
# Apply the mean function to each data.frame&amp;#39;s mpg column
apply &amp;lt;- lapply(
  split,
  function(x) {
    x[, &amp;quot;meanMpg&amp;quot;] &amp;lt;- mean(x$mpg)
    x
  }
)
# Stitch each of the lists back into one data.frame
combine &amp;lt;- do.call(rbind, unname(apply))
combine
#                      mpg cyl  disp  hp drat    wt  qsec vs am gear carb  meanMpg
# Merc 240D           24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2 22.90000
# Merc 230            22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2 22.90000
# Toyota Corona       21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1 22.90000
# Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1 28.07500
# Fiat 128            32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1 28.07500
# Honda Civic         30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2 28.07500
# Toyota Corolla      33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1 28.07500
# Fiat X1-9           27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1 28.07500
# Porsche 914-2       26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2 28.07500
# Lotus Europa        30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2 28.07500
# Volvo 142E          21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2 28.07500
# Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1 19.12500
# Valiant             18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1 19.12500
# Merc 280            19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4 19.12500
# Merc 280C           17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4 19.12500
# Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4 20.56667
# Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4 20.56667
# Ferrari Dino        19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6 20.56667
# Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2 15.05000
# Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4 15.05000
# Merc 450SE          16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3 15.05000
# Merc 450SL          17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3 15.05000
# Merc 450SLC         15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3 15.05000
# Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4 15.05000
# Lincoln Continental 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4 15.05000
# Chrysler Imperial   14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4 15.05000
# Dodge Challenger    15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2 15.05000
# AMC Javelin         15.2   8 304.0 150 3.15 3.435 17.30  0  0    3    2 15.05000
# Camaro Z28          13.3   8 350.0 245 3.73 3.840 15.41  0  0    3    4 15.05000
# Pontiac Firebird    19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2 15.05000
# Ford Pantera L      15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4 15.40000
# Maserati Bora       15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8 15.40000&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that here I &lt;code&gt;unname()&lt;/code&gt; the list of &lt;code&gt;data.frame&lt;/code&gt;s to avoid &lt;code&gt;rbind()&lt;/code&gt; prepending the row names with the group information. This is a really nice, flexible way to perform grouped operations using &lt;code&gt;base&lt;/code&gt;. There are in fact many other ways that this type of operation can be achieved; the flexibility of &lt;code&gt;base&lt;/code&gt; is what makes it so great.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;the-poorman-way&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The &lt;code&gt;poorman&lt;/code&gt; Way&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;poorman&lt;/code&gt; aims to be a direct replacement for &lt;code&gt;dplyr&lt;/code&gt;, the idea being that loading &lt;code&gt;poorman&lt;/code&gt; and running your script written with &lt;code&gt;dplyr&lt;/code&gt; code should return the same results. Therefore if you’re familiar with the &lt;code&gt;dplyr&lt;/code&gt; API then the next piece of code should look very familiar.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(poorman)
mtcars %&amp;gt;%
  group_by(am, cyl) %&amp;gt;%
  mutate(meanMpg = mean(mpg))
#                      mpg cyl  disp  hp drat    wt  qsec vs am gear carb  meanMpg
# Merc 240D           24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2 22.90000
# Merc 230            22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2 22.90000
# Toyota Corona       21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1 22.90000
# Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1 28.07500
# Fiat 128            32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1 28.07500
# Honda Civic         30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2 28.07500
# Toyota Corolla      33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1 28.07500
# Fiat X1-9           27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1 28.07500
# Porsche 914-2       26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2 28.07500
# Lotus Europa        30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2 28.07500
# Volvo 142E          21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2 28.07500
# Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1 19.12500
# Valiant             18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1 19.12500
# Merc 280            19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4 19.12500
# Merc 280C           17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4 19.12500
# Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4 20.56667
# Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4 20.56667
# Ferrari Dino        19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6 20.56667
# Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2 15.05000
# Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4 15.05000
# Merc 450SE          16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3 15.05000
# Merc 450SL          17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3 15.05000
# Merc 450SLC         15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3 15.05000
# Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4 15.05000
# Lincoln Continental 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4 15.05000
# Chrysler Imperial   14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4 15.05000
# Dodge Challenger    15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2 15.05000
# AMC Javelin         15.2   8 304.0 150 3.15 3.435 17.30  0  0    3    2 15.05000
# Camaro Z28          13.3   8 350.0 245 3.73 3.840 15.41  0  0    3    4 15.05000
# Pontiac Firebird    19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2 15.05000
# Ford Pantera L      15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4 15.40000
# Maserati Bora       15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8 15.40000
# 
# Groups:  am, cyl&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In order to achieve this, I need to have a way to perform grouped operations for functions such as &lt;code&gt;mutate()&lt;/code&gt; and &lt;code&gt;filter()&lt;/code&gt;. The easiest solution I could think of therefore is an S3 class system. So the &lt;code&gt;group_by()&lt;/code&gt; function simply applies a &lt;code&gt;&#34;grouped_data&#34;&lt;/code&gt; class to the data and then the &lt;code&gt;mutate()&lt;/code&gt; S3 generic knows to dispatch to the &lt;code&gt;mutate.grouped_data()&lt;/code&gt; method. For more information on the S3 class system I recommend checking out &lt;a href=&#34;https://adv-r.hadley.nz/s3.html&#34;&gt;Advanced R&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;ungrouping&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Ungrouping&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;poorman&lt;/code&gt; also offers a replica of the &lt;code&gt;dplyr::ungroup()&lt;/code&gt; function. Let’s take a look.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars %&amp;gt;%
  group_by(am, cyl) %&amp;gt;%
  mutate(meanMpg = mean(mpg)) %&amp;gt;%
  ungroup(am)
#                      mpg cyl  disp  hp drat    wt  qsec vs am gear carb  meanMpg
# Merc 240D           24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2 22.90000
# Merc 230            22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2 22.90000
# Toyota Corona       21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1 22.90000
# Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1 28.07500
# Fiat 128            32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1 28.07500
# Honda Civic         30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2 28.07500
# Toyota Corolla      33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1 28.07500
# Fiat X1-9           27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1 28.07500
# Porsche 914-2       26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2 28.07500
# Lotus Europa        30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2 28.07500
# Volvo 142E          21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2 28.07500
# Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1 19.12500
# Valiant             18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1 19.12500
# Merc 280            19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4 19.12500
# Merc 280C           17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4 19.12500
# Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4 20.56667
# Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4 20.56667
# Ferrari Dino        19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6 20.56667
# Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2 15.05000
# Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4 15.05000
# Merc 450SE          16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3 15.05000
# Merc 450SL          17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3 15.05000
# Merc 450SLC         15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3 15.05000
# Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4 15.05000
# Lincoln Continental 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4 15.05000
# Chrysler Imperial   14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4 15.05000
# Dodge Challenger    15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2 15.05000
# AMC Javelin         15.2   8 304.0 150 3.15 3.435 17.30  0  0    3    2 15.05000
# Camaro Z28          13.3   8 350.0 245 3.73 3.840 15.41  0  0    3    4 15.05000
# Pontiac Firebird    19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2 15.05000
# Ford Pantera L      15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4 15.40000
# Maserati Bora       15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8 15.40000
# 
# Groups:  cyl&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We see here that the printing method tells us the remaining group: &lt;code&gt;cyl&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;additional-functionality&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Additional Functionality&lt;/h1&gt;
&lt;div id=&#34;the-pipe&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The Pipe&lt;/h2&gt;
&lt;p&gt;You will have noticed that I am piping commands together in the above section, however I am not using the &lt;code&gt;magrittr&lt;/code&gt; pipe. I implemented my own version which is a very small piece of code. This means users no longer need to load &lt;code&gt;magrittr&lt;/code&gt; separately (previously &lt;code&gt;poorman&lt;/code&gt; only had &lt;code&gt;magrittr&lt;/code&gt; as a suggested package so as not to force the installation on users).&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;`%&amp;gt;%` &amp;lt;- function(lhs, rhs) {
  lhs &amp;lt;- substitute(lhs)
  rhs &amp;lt;- substitute(rhs)
  eval(as.call(c(rhs[[1L]], lhs, as.list(rhs[-1L]))), envir = parent.frame())
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;rename&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Rename&lt;/h2&gt;
&lt;p&gt;I also managed to add &lt;code&gt;rename()&lt;/code&gt;. For this I took advantage of &lt;code&gt;colnames&amp;lt;-&lt;/code&gt; in combination with the &lt;code&gt;inset()&lt;/code&gt; function I defined in my last post (&lt;code&gt;[&amp;lt;-&lt;/code&gt;). I don’t want to make this post too heavy on the code so feel free to take a look at the &lt;a href=&#34;https://github.com/nathaneastwood/poorman/blob/master/R/rename.R&#34;&gt;code&lt;/a&gt; yourself to see how exactly I achieved this.&lt;/p&gt;
&lt;p&gt;Now I am able to pass key-value pairs of unquoted column names to rename columns. See below for an example.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars %&amp;gt;%
  rename(MPG = mpg, numCyls = cyl)
#                      MPG numCyls  disp  hp drat    wt  qsec vs am gear carb
# Mazda RX4           21.0       6 160.0 110 3.90 2.620 16.46  0  1    4    4
# Mazda RX4 Wag       21.0       6 160.0 110 3.90 2.875 17.02  0  1    4    4
# Datsun 710          22.8       4 108.0  93 3.85 2.320 18.61  1  1    4    1
# Hornet 4 Drive      21.4       6 258.0 110 3.08 3.215 19.44  1  0    3    1
# Hornet Sportabout   18.7       8 360.0 175 3.15 3.440 17.02  0  0    3    2
# Valiant             18.1       6 225.0 105 2.76 3.460 20.22  1  0    3    1
# Duster 360          14.3       8 360.0 245 3.21 3.570 15.84  0  0    3    4
# Merc 240D           24.4       4 146.7  62 3.69 3.190 20.00  1  0    4    2
# Merc 230            22.8       4 140.8  95 3.92 3.150 22.90  1  0    4    2
# Merc 280            19.2       6 167.6 123 3.92 3.440 18.30  1  0    4    4
# Merc 280C           17.8       6 167.6 123 3.92 3.440 18.90  1  0    4    4
# Merc 450SE          16.4       8 275.8 180 3.07 4.070 17.40  0  0    3    3
# Merc 450SL          17.3       8 275.8 180 3.07 3.730 17.60  0  0    3    3
# Merc 450SLC         15.2       8 275.8 180 3.07 3.780 18.00  0  0    3    3
# Cadillac Fleetwood  10.4       8 472.0 205 2.93 5.250 17.98  0  0    3    4
# Lincoln Continental 10.4       8 460.0 215 3.00 5.424 17.82  0  0    3    4
# Chrysler Imperial   14.7       8 440.0 230 3.23 5.345 17.42  0  0    3    4
# Fiat 128            32.4       4  78.7  66 4.08 2.200 19.47  1  1    4    1
# Honda Civic         30.4       4  75.7  52 4.93 1.615 18.52  1  1    4    2
# Toyota Corolla      33.9       4  71.1  65 4.22 1.835 19.90  1  1    4    1
# Toyota Corona       21.5       4 120.1  97 3.70 2.465 20.01  1  0    3    1
# Dodge Challenger    15.5       8 318.0 150 2.76 3.520 16.87  0  0    3    2
# AMC Javelin         15.2       8 304.0 150 3.15 3.435 17.30  0  0    3    2
# Camaro Z28          13.3       8 350.0 245 3.73 3.840 15.41  0  0    3    4
# Pontiac Firebird    19.2       8 400.0 175 3.08 3.845 17.05  0  0    3    2
# Fiat X1-9           27.3       4  79.0  66 4.08 1.935 18.90  1  1    4    1
# Porsche 914-2       26.0       4 120.3  91 4.43 2.140 16.70  0  1    5    2
# Lotus Europa        30.4       4  95.1 113 3.77 1.513 16.90  1  1    5    2
# Ford Pantera L      15.8       8 351.0 264 4.22 3.170 14.50  0  1    5    4
# Ferrari Dino        19.7       6 145.0 175 3.62 2.770 15.50  0  1    5    6
# Maserati Bora       15.0       8 301.0 335 3.54 3.570 14.60  0  1    5    8
# Volvo 142E          21.4       4 121.0 109 4.11 2.780 18.60  1  1    4    2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using this function, I was able to implement key-value &lt;code&gt;select()&lt;/code&gt; statements too!&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars %&amp;gt;%
  select(MPG = mpg, numCyls = cyl, numGears = gear)
#                      MPG numCyls numGears
# Mazda RX4           21.0       6        4
# Mazda RX4 Wag       21.0       6        4
# Datsun 710          22.8       4        4
# Hornet 4 Drive      21.4       6        3
# Hornet Sportabout   18.7       8        3
# Valiant             18.1       6        3
# Duster 360          14.3       8        3
# Merc 240D           24.4       4        4
# Merc 230            22.8       4        4
# Merc 280            19.2       6        4
# Merc 280C           17.8       6        4
# Merc 450SE          16.4       8        3
# Merc 450SL          17.3       8        3
# Merc 450SLC         15.2       8        3
# Cadillac Fleetwood  10.4       8        3
# Lincoln Continental 10.4       8        3
# Chrysler Imperial   14.7       8        3
# Fiat 128            32.4       4        4
# Honda Civic         30.4       4        4
# Toyota Corolla      33.9       4        4
# Toyota Corona       21.5       4        3
# Dodge Challenger    15.5       8        3
# AMC Javelin         15.2       8        3
# Camaro Z28          13.3       8        3
# Pontiac Firebird    19.2       8        3
# Fiat X1-9           27.3       4        4
# Porsche 914-2       26.0       4        5
# Lotus Europa        30.4       4        5
# Ford Pantera L      15.8       8        5
# Ferrari Dino        19.7       6        5
# Maserati Bora       15.0       8        5
# Volvo 142E          21.4       4        4&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;summary&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;Finally I have added a copy of the &lt;code&gt;summarise()&lt;/code&gt; function. This was probably the trickiest piece of code to write for the package and I am not completely satisfied with my solution although it works and is seemingly quite quick (on my 2016 MacBook Pro). If you’re interested in taking a look at the implementation and making suggestions then the code can be found &lt;a href=&#34;https://github.com/nathaneastwood/poorman/blob/master/R/summarise.R&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars %&amp;gt;%
  group_by(am, cyl) %&amp;gt;%
  summarise(meanMpg = mean(mpg), sumDisp = sum(disp))
#   am cyl  meanMpg sumDisp
# 1  0   4     22.9   407.6
# 2  1   4   28.075   748.9
# 3  0   6   19.125   818.2
# 4  1   6 20.56667     465
# 5  0   8    15.05  4291.4
# 6  1   8     15.4     652&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Recently there was a very interesting Twitter discussion on this topic which led to an comprehensive list of examples for performing this operation in &lt;code&gt;base&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet tw-align-center&#34;&gt;
&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;
How would you write this in base R?&lt;br&gt;&lt;br&gt;mtcars %&amp;gt;% &lt;br&gt; group_by(cyl) %&amp;gt;% &lt;br&gt; summarise(mean = mean(disp), n = n())&lt;br&gt;&lt;br&gt;I&#39;ve written up three approaches in &lt;a href=&#34;https://t.co/BBnXSDSf67&#34;&gt;https://t.co/BBnXSDSf67&lt;/a&gt;. Is there a better way? &lt;a href=&#34;https://twitter.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt;
&lt;/p&gt;
— Hadley Wickham (&lt;span class=&#34;citation&#34;&gt;@hadleywickham&lt;/span&gt;) &lt;a href=&#34;https://twitter.com/hadleywickham/status/1231252596712771585?ref_src=twsrc%5Etfw&#34;&gt;February 22, 2020&lt;/a&gt;
&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;I believe that &lt;code&gt;poorman&lt;/code&gt; now offers the core of what &lt;code&gt;dplyr&lt;/code&gt; has to offer using only &lt;code&gt;base&lt;/code&gt;, therefore zero dependencies (not including development based dependencies such as &lt;code&gt;roxygen2&lt;/code&gt;). I now need to really start writing some serious tests which I will endeavour to do using &lt;a href=&#34;https://github.com/markvanderloo/tinytest&#34;&gt;&lt;code&gt;tinytest&lt;/code&gt;&lt;/a&gt; before adding any additional functionality. Without tests, any package is rather worthless in my opinion. If there is functionality you would like to see added to the package then please feel free to submit an issue or open a pull request.&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Including Function Factories in an R Package: Using Collate</title>
      <link>/2020/02/25/including-function-factories-in-an-r-package-using-collate/</link>
      <pubDate>Tue, 25 Feb 2020 20:12:00 -0500</pubDate>
      
      <guid>/2020/02/25/including-function-factories-in-an-r-package-using-collate/</guid>
      <description>


&lt;div id=&#34;introduction&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;This week I was working on a package which included a function factory. A function factory is a function which returns a function. The problem I faced was that when I was running &lt;code&gt;R CMD check&lt;/code&gt; on my package, the check informed me my package had several issues which on first glance were confusing and seemingly shouldn’t have been reported. In this blog post, we’ll discover why.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;function-factory-example&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Function Factory Example&lt;/h1&gt;
&lt;p&gt;Let’s write a function factory, here I shamelessly use the example from &lt;a href=&#34;https://adv-r.hadley.nz/function-factories.html&#34;&gt;Advanced R&lt;/a&gt;. We will use a function factory called &lt;code&gt;power1()&lt;/code&gt; to create two additional functions &lt;code&gt;square()&lt;/code&gt; and &lt;code&gt;cube()&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;power1 &amp;lt;- function(exp) {
  function(x) {
    x ^ exp
  }
}

square &amp;lt;- power1(2)
cube &amp;lt;- power1(3)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By assigning &lt;code&gt;power1(2)&lt;/code&gt; to the object &lt;code&gt;square&lt;/code&gt;, we have created a new function, &lt;code&gt;square()&lt;/code&gt;, which when given a value for &lt;code&gt;x&lt;/code&gt; will return the result of &lt;code&gt;x&lt;/code&gt; to the power of two. Similarly the &lt;code&gt;cube()&lt;/code&gt; function will return the result of &lt;code&gt;x&lt;/code&gt; to the power of three. Let’s see this in action.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;square(3)
# [1] 9
cube(3)
# [1] 27&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To understand more about function factories, I strongly recommend reading the &lt;a href=&#34;https://adv-r.hadley.nz/function-factories.html&#34;&gt;Advanced R&lt;/a&gt; chapter on function factories.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;could-not-find-function-power1&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Could Not Find Function “power1”&lt;/h1&gt;
&lt;p&gt;I was working on a package which contained my function factory in file A and multiple “child” functions, which were generated by that function, in file B. Everything seemed to be working fine; locally I could install the package and the &lt;code&gt;R CMD check&lt;/code&gt; ran without any &lt;code&gt;ERROR&lt;/code&gt;s, &lt;code&gt;WARNING&lt;/code&gt;s or &lt;code&gt;NOTE&lt;/code&gt;s. However when I ran the code within my CI/CD pipeline, the &lt;code&gt;R CMD check&lt;/code&gt; gave me the following set of messages.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;R CMD check results
1 error  | 3 warnings | 2 notes
checking for missing documentation entries ... ERROR
Error: cannot source package code:
could not find function &amp;quot;power1&amp;quot;
Execution halted

checking S3 generic/method consistency ... WARNING
Error: cannot source package code:
could not find function &amp;quot;power1&amp;quot;
Execution halted
See section &amp;#39;Generic functions and methods&amp;#39; in the &amp;#39;Writing R
Extensions&amp;#39; manual.

checking replacement functions ... WARNING
Error: cannot source package code:
could not find function &amp;quot;power1&amp;quot;
Execution halted
The argument of a replacement function which corresponds to the right
hand side must be named &amp;#39;value&amp;#39;.

checking for code/documentation mismatches ... WARNING
Error: cannot source package code:
could not find function &amp;quot;power1&amp;quot;
Execution halted

checking R code for possible problems ... NOTE
Error: cannot source package code:
could not find function &amp;quot;power1&amp;quot;
Execution halted

checking Rd \usage sections ... NOTE
Error: cannot source package code:
could not find function &amp;quot;power1&amp;quot;
Execution halted
The \usage entries for S3 methods should use the \method markup and not
their full name.
See chapter &amp;#39;Writing R documentation files&amp;#39; in the &amp;#39;Writing R
Extensions&amp;#39; manual.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This had me really stumped for a while - especially as the messages given by &lt;code&gt;R CMD check&lt;/code&gt; were talking about things that were unrelated to my code as I have no S3 methods in my package, my documentation was up to date and the function was definitely there and checked into my git repository. So why then was this not working within my CI/CD pipeline? Finally the penny dropped and I finally realised that it is because when R is checking the package, it must be sourcing &lt;code&gt;square()&lt;/code&gt; and &lt;code&gt;cube()&lt;/code&gt; &lt;em&gt;before&lt;/em&gt; it has sourced &lt;code&gt;power1()&lt;/code&gt;. Therefore it cannot assign the output of &lt;code&gt;power1()&lt;/code&gt; to &lt;code&gt;square&lt;/code&gt; and &lt;code&gt;cube&lt;/code&gt; since it doesn’t “exist” at that point.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;the-solution&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;The Solution&lt;/h1&gt;
&lt;p&gt;The solution, it turns out, is very straight forward. We must tell R to collate the files in a particular order and we can do this by specifying the order in the &lt;code&gt;Collate:&lt;/code&gt; field of the &lt;code&gt;DESCRIPTION&lt;/code&gt; file. But even better, as I am using &lt;code&gt;roxygen2&lt;/code&gt;, I can use the &lt;code&gt;@include&lt;/code&gt; tag to state that one file needs another to work. Therefore as I need to make sure that file &lt;code&gt;power1.R&lt;/code&gt; is loaded before &lt;code&gt;square.R&lt;/code&gt; and &lt;code&gt;cube.R&lt;/code&gt;, I simply include &lt;code&gt;@include power1.R&lt;/code&gt; in the other files. &lt;code&gt;roxygen2&lt;/code&gt; takes care of ordering the &lt;code&gt;Collate:&lt;/code&gt; field to satisfy these restrictions. As another handy tip, let’s say &lt;code&gt;square()&lt;/code&gt; and &lt;code&gt;cube()&lt;/code&gt; were defined in a file together which is separate from the &lt;code&gt;power1.R&lt;/code&gt; file, we can include the following lines of code at the top of the child function file.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#&amp;#39; @include power1.R`
NULL&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And &lt;code&gt;roxygen2&lt;/code&gt; will again take care of the &lt;code&gt;Collate:&lt;/code&gt; field for us automatically.&lt;/p&gt;
&lt;p&gt;As for why everything worked locally but not in my CI/CD pipeline, I can only assume that as the CI/CD pipeline runs on a different machine, R is using some different method to source and collate the files. So it is better to be safe than sorry and explicitly include the order of the files in the &lt;code&gt;Collate:&lt;/code&gt; field.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;To conclude, if you plan on including a function factory in your package where the factories’ child functions are in a different file, it is really important that you tell R the order in which it should source these files. You can achieve this simply with &lt;code&gt;roxygen2&lt;/code&gt; by using the &lt;code&gt;@include&lt;/code&gt; tag - specifying the function factory file name - within the file(s) of the function(s) generated by the function factory. &lt;code&gt;roxygen2&lt;/code&gt; will then automatically fill and sort the &lt;code&gt;Collate:&lt;/code&gt; field within your &lt;code&gt;DESCRIPTION&lt;/code&gt; file.&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Building A base dplyr With Primitives</title>
      <link>/2020/02/15/building-a-base-dplyr-with-primitives/</link>
      <pubDate>Sat, 15 Feb 2020 20:12:00 -0500</pubDate>
      
      <guid>/2020/02/15/building-a-base-dplyr-with-primitives/</guid>
      <description>


&lt;div id=&#34;introduction&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;In one of my &lt;a href=&#34;https://nathaneastwood.github.io/2020/02/01/get-and-set-list-elements-with-magrittr/&#34;&gt;latest posts&lt;/a&gt;, I discussed the idea of turning base R’s get and set operators (&lt;code&gt;[&lt;/code&gt;, &lt;code&gt;[[&lt;/code&gt;, &lt;code&gt;[&amp;lt;-&lt;/code&gt;, &lt;code&gt;[[&amp;lt;-&lt;/code&gt;) into human readable and pipeable functions. It was kindly pointed out in the comments that the &lt;code&gt;get()&lt;/code&gt; and &lt;code&gt;set()&lt;/code&gt; functions I defined in that blog post are actually exported in the &lt;code&gt;magrittr&lt;/code&gt; package as &lt;code&gt;magrittr::extract2()&lt;/code&gt; (&lt;code&gt;[[&lt;/code&gt;) and &lt;code&gt;magrittr::inset2()&lt;/code&gt; (&lt;code&gt;[[&amp;lt;-&lt;/code&gt;). In fact, there are a whole host of “alias” functions exported by &lt;code&gt;magrittr&lt;/code&gt;, see &lt;code&gt;?magrittr::extract2&lt;/code&gt; for more. However if we are developing a package, we may not necessarily want to &lt;code&gt;Import: magrittr&lt;/code&gt;, we may only want to &lt;code&gt;Suggest&lt;/code&gt; it as a package that complements our package. This is especially true when the functions we will be importing are simple aliases of other functions that we can just as easily create ourselves. Now sure, a lot of people already have and use &lt;code&gt;magrittr&lt;/code&gt;, in which case they can use it, but not everyone wants it or uses it, so we shouldn’t enforce that dependency on users.&lt;/p&gt;
&lt;p&gt;Take for example if we were to create a package that recreates &lt;code&gt;dplyr&lt;/code&gt;’s main verbs, &lt;code&gt;select()&lt;/code&gt;; &lt;code&gt;filter()&lt;/code&gt;; &lt;code&gt;mutate()&lt;/code&gt;; and &lt;code&gt;arrange()&lt;/code&gt;, using base R only. Think of it as a “poor man’s” dplyr, of course I jest - &lt;code&gt;base&lt;/code&gt; is awesome. Oftentimes the main complaint I hear about &lt;code&gt;dplyr&lt;/code&gt; is the sheer number of dependencies it has and the installation times that come with that; not to mention APIs have changed a few times over the years. &lt;code&gt;base&lt;/code&gt; on the other hand already comes pre-installed with R and the API is extremely stable. The reason people like &lt;code&gt;dplyr&lt;/code&gt;, however, is because the API on offer is extremely flexible and easy to understand. This blog post will show how we can recreate these verbs using base R and aliases to R’s operator functions and use them in conjunction with &lt;code&gt;magrittr&lt;/code&gt;.&lt;/p&gt;
&lt;div id=&#34;select&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Select&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;dplyr::select()&lt;/code&gt; allows the user to subset the columns of a &lt;code&gt;data.frame&lt;/code&gt; and always return a &lt;code&gt;data.frame&lt;/code&gt;. Thus to recreate this function we will need the operator for subsetting columns of a &lt;code&gt;data.frame&lt;/code&gt; which is &lt;code&gt;[&lt;/code&gt;, or more specifically, &lt;code&gt;[.data.frame&lt;/code&gt;. Let’s take a look at the arguments for this function.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;args(`[.data.frame`)
# function (x, i, j, drop = if (missing(i)) TRUE else length(cols) == 
#     1) 
# NULL&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We see that it takes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;x&lt;/code&gt; - the &lt;code&gt;data.frame&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;i&lt;/code&gt; - the rows to subset&lt;/li&gt;
&lt;li&gt;&lt;code&gt;j&lt;/code&gt; - the columns to subset&lt;/li&gt;
&lt;li&gt;&lt;code&gt;drop&lt;/code&gt; - whether to return a vector if only one column is left&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We will define our wrapper for the &lt;code&gt;[&lt;/code&gt; function in the same way that &lt;code&gt;magrittr&lt;/code&gt; does.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;extract &amp;lt;- `[`&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As this is an S3 generic, R will know to dispatch to &lt;code&gt;[.data.frame&lt;/code&gt; when it is passed a &lt;code&gt;data.frame&lt;/code&gt;. Hence, we can now define a &lt;code&gt;select()&lt;/code&gt; function which is similar in functionality to that of &lt;code&gt;dplyr::select()&lt;/code&gt;. Note that we tell R that we wish to subset all of the rows in the &lt;code&gt;i&lt;/code&gt; position by leaving the argument blank.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;select &amp;lt;- function(.data, ...) {
  cols &amp;lt;- vapply(substitute(...()), deparse, NA_character_)
  extract(.data, , cols, drop = FALSE)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This function uses a couple of tricks here, so I’ll break them down. To use non-standard evaluation in the same way that &lt;code&gt;dplyr&lt;/code&gt; does, that is to pass non-quoted column names, we must deparse them. We loop over the columns passed via &lt;code&gt;...&lt;/code&gt; using a &lt;code&gt;vapply()&lt;/code&gt;. The &lt;code&gt;substitute(...())&lt;/code&gt; gives us a list-like object of all the symbols we pass which we can loop over. Using this function, we can now select a single column.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars %&amp;gt;% select(mpg)
#                      mpg
# Mazda RX4           21.0
# Mazda RX4 Wag       21.0
# Datsun 710          22.8
# Hornet 4 Drive      21.4
# Hornet Sportabout   18.7
# Valiant             18.1
# Duster 360          14.3
# Merc 240D           24.4
# Merc 230            22.8
# ... 23 rows omitted&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or multiple columns by passing a vector.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars %&amp;gt;% select(mpg, cyl)
#                      mpg cyl
# Mazda RX4           21.0   6
# Mazda RX4 Wag       21.0   6
# Datsun 710          22.8   4
# Hornet 4 Drive      21.4   6
# Hornet Sportabout   18.7   8
# Valiant             18.1   6
# Duster 360          14.3   8
# Merc 240D           24.4   4
# Merc 230            22.8   4
# ... 23 rows omitted&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And of course, this function works without &lt;code&gt;magrittr&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;select(mtcars, mpg, cyl)
#                      mpg cyl
# Mazda RX4           21.0   6
# Mazda RX4 Wag       21.0   6
# Datsun 710          22.8   4
# Hornet 4 Drive      21.4   6
# Hornet Sportabout   18.7   8
# Valiant             18.1   6
# Duster 360          14.3   8
# Merc 240D           24.4   4
# Merc 230            22.8   4
# ... 23 rows omitted&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For bonus points, we can write an equivalent of &lt;code&gt;dplyr::pull()&lt;/code&gt; by setting the &lt;code&gt;drop = TRUE&lt;/code&gt; argument and removing the &lt;code&gt;cols&lt;/code&gt; parameter since we are only dealing with one column.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;pull &amp;lt;- function(.data, var) {
  var &amp;lt;- deparse(substitute(var))
  stopifnot(length(var) == 1)
  extract(.data, , var, drop = TRUE)
}
mtcars %&amp;gt;% pull(mpg)
#  [1] 21.0 21.0 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 17.8 16.4 17.3 15.2 10.4 10.4 14.7
# [18] 32.4 30.4 33.9 21.5 15.5 15.2 13.3 19.2 27.3 26.0 30.4 15.8 19.7 15.0 21.4&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;filter&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Filter&lt;/h2&gt;
&lt;p&gt;As we saw in the previous section, &lt;code&gt;[.data.frame&lt;/code&gt; takes &lt;code&gt;i&lt;/code&gt; as an argument which represents the rows to filter. Thus we can use a similar method to that used for &lt;code&gt;select()&lt;/code&gt; only in this case, we must build the expressions by which to filter and separate them with an ampersand from which we can parse and evaluate.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;filter &amp;lt;- function(.data, ...) {
  conditions &amp;lt;- paste(vapply(substitute(...()), deparse, NA_character_), collapse = &amp;quot; &amp;amp; &amp;quot;)
  extract(.data, with(.data, eval(parse(text = conditions))), )
}
mtcars %&amp;gt;% filter(cyl == 4)
#                 mpg cyl  disp  hp drat    wt  qsec vs am gear carb
# Datsun 710     22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
# Merc 240D      24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
# Merc 230       22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
# Fiat 128       32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
# Honda Civic    30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
# Toyota Corolla 33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
# Toyota Corona  21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
# Fiat X1-9      27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
# Porsche 914-2  26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
# ... 2 rows omitted
mtcars %&amp;gt;% filter(cyl &amp;lt;= 5 &amp;amp; am &amp;gt; 0)
#                 mpg cyl  disp  hp drat    wt  qsec vs am gear carb
# Datsun 710     22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
# Fiat 128       32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
# Honda Civic    30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
# Toyota Corolla 33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
# Fiat X1-9      27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
# Porsche 914-2  26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
# Lotus Europa   30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
# Volvo 142E     21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2
mtcars %&amp;gt;% filter(cyl == 4 | cyl == 8)
#                      mpg cyl  disp  hp drat    wt  qsec vs am gear carb
# Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
# Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
# Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
# Merc 240D           24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
# Merc 230            22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
# Merc 450SE          16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3
# Merc 450SL          17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3
# Merc 450SLC         15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3
# Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4
# ... 16 rows omitted
mtcars %&amp;gt;% filter(!(cyl %in% c(4, 6)), am != 0)
#                 mpg cyl disp  hp drat   wt qsec vs am gear carb
# Ford Pantera L 15.8   8  351 264 4.22 3.17 14.5  0  1    5    4
# Maserati Bora  15.0   8  301 335 3.54 3.57 14.6  0  1    5    8&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can also get a copy of &lt;code&gt;dplyr::slice()&lt;/code&gt; really cheaply.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;slice &amp;lt;- function(.data, ...) {
  stopifnot(is.numeric(...) || is.integer(...))
  extract(.data, ..., )
}
mtcars %&amp;gt;% slice(1:3)
#                mpg cyl disp  hp drat    wt  qsec vs am gear carb
# Mazda RX4     21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
# Mazda RX4 Wag 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
# Datsun 710    22.8   4  108  93 3.85 2.320 18.61  1  1    4    1&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;arrange&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Arrange&lt;/h2&gt;
&lt;p&gt;The final function using the &lt;code&gt;extract()&lt;/code&gt; alias that I want to highlight is &lt;code&gt;arrange()&lt;/code&gt;. I want to highlight this function because of the required trick with &lt;code&gt;eval.parent()&lt;/code&gt; (note there are &lt;a href=&#34;https://stackoverflow.com/a/58757430/3759418&#34;&gt;other ways&lt;/a&gt; we could achieve this).&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;arrange &amp;lt;- function(.data, ...) {
  rows &amp;lt;- eval.parent(substitute(with(.data, order(...))))
  extract(.data, rows, , drop = FALSE)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We use &lt;code&gt;eval.parent()&lt;/code&gt; instead of &lt;code&gt;eval()&lt;/code&gt;, because the &lt;a href=&#34;https://stackoverflow.com/a/53215820/300187&#34;&gt;&lt;code&gt;eval()&lt;/code&gt;/&lt;code&gt;substitute()&lt;/code&gt; combo doesn’t play well with nested functions&lt;/a&gt;. The &lt;code&gt;eval.parent()&lt;/code&gt; trick has been &lt;a href=&#34;https://stackoverflow.com/a/58239679/300187&#34;&gt;proposed by @MoodyMudskipper&lt;/a&gt; as a way to address this problem and allows us to seamlessly use &lt;code&gt;arrange()&lt;/code&gt; inside other functions, including &lt;code&gt;magrittr&lt;/code&gt; pipes:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars %&amp;gt;% arrange(mpg)
#                      mpg cyl  disp  hp drat    wt  qsec vs am gear carb
# Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4
# Lincoln Continental 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4
# Camaro Z28          13.3   8 350.0 245 3.73 3.840 15.41  0  0    3    4
# Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
# Chrysler Imperial   14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4
# Maserati Bora       15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8
# Merc 450SLC         15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3
# AMC Javelin         15.2   8 304.0 150 3.15 3.435 17.30  0  0    3    2
# Dodge Challenger    15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2
# ... 23 rows omitted
mtcars %&amp;gt;% arrange(cyl, mpg)
#                      mpg cyl  disp  hp drat    wt  qsec vs am gear carb
# Volvo 142E          21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2
# Toyota Corona       21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
# Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
# Merc 230            22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
# Merc 240D           24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
# Porsche 914-2       26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
# Fiat X1-9           27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
# Honda Civic         30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
# Lotus Europa        30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
# ... 23 rows omitted&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Thanks go to Artem Sokolov for &lt;a href=&#34;https://stackoverflow.com/a/58757463/3759418&#34;&gt;pointing this out&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;mutate&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Mutate&lt;/h2&gt;
&lt;p&gt;If we wish to create new columns in our dataset, particularly columns created using existing columns in the data, we must use the &lt;code&gt;[&amp;lt;-&lt;/code&gt; operator, specifically, &lt;code&gt;[&amp;lt;-.data.frame&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;args(`[&amp;lt;-.data.frame`)
# function (x, i, j, value) 
# NULL&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;[&amp;lt;-.data.frame&lt;/code&gt; takes the arguments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;x&lt;/code&gt; - the data&lt;/li&gt;
&lt;li&gt;&lt;code&gt;i&lt;/code&gt; - the rows to create&lt;/li&gt;
&lt;li&gt;&lt;code&gt;j&lt;/code&gt; - the columns to create&lt;/li&gt;
&lt;li&gt;&lt;code&gt;value&lt;/code&gt; - the value to give to the rows/columns&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We will assign this operator to &lt;code&gt;inset&lt;/code&gt; - the same as &lt;code&gt;magrittr&lt;/code&gt; does.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;inset &amp;lt;- `[&amp;lt;-`&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here we &lt;code&gt;lapply()&lt;/code&gt; over each of the conditions to return a list of vectored results of our expressions. We then use the &lt;code&gt;inset()&lt;/code&gt; function to add these vectors as new columns to the &lt;code&gt;data.frame&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mutate &amp;lt;- function(.data, ...) {
  conditions &amp;lt;- vapply(substitute(...()), deparse, NA_character_)
  new_data &amp;lt;- lapply(
    conditions,
    function(x, .data) with(.data, eval(parse(text = x))),
    .data
  )
  inset(.data, , names(conditions), new_data)
}
mtcars %&amp;gt;% mutate(mpg2 = mpg * 2)
#                      mpg cyl  disp  hp drat    wt  qsec vs am gear carb mpg2
# Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4 42.0
# Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4 42.0
# Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1 45.6
# Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1 42.8
# Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2 37.4
# Valiant             18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1 36.2
# Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4 28.6
# Merc 240D           24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2 48.8
# Merc 230            22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2 45.6
# ... 23 rows omitted
mtcars %&amp;gt;% mutate(mpg2 = mpg * 2, cyl2 = cyl * 2)
#                      mpg cyl  disp  hp drat    wt  qsec vs am gear carb mpg2 cyl2
# Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4 42.0   12
# Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4 42.0   12
# Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1 45.6    8
# Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1 42.8   12
# Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2 37.4   16
# Valiant             18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1 36.2   12
# Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4 28.6   16
# Merc 240D           24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2 48.8    8
# Merc 230            22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2 45.6    8
# ... 23 rows omitted&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that unlike &lt;code&gt;dplyr::mutate()&lt;/code&gt;, we cannot create columns based on expressions we pass, for example, the following would not work.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars %&amp;gt;% mutate(mpg2 = mpg * 2, mpg3 = mpg2 * 3)
# Error in eval(parse(text = x)): object &amp;#39;mpg2&amp;#39; not found&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As a bonus, we can combine our &lt;code&gt;mutate()&lt;/code&gt; function with &lt;code&gt;extract()&lt;/code&gt; to create a copy of &lt;code&gt;dplyr::transmute()&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;transmute &amp;lt;- function(.data, ...) {
  conditions &amp;lt;- vapply(substitute(...()), deparse, NA_character_)
  mutated &amp;lt;- mutate(.data, ...)
  extract(mutated, names(conditions))
}
mtcars %&amp;gt;% transmute(mpg2 = mpg * 2, cyl2 = cyl * 2)
#                     mpg2 cyl2
# Mazda RX4           42.0   12
# Mazda RX4 Wag       42.0   12
# Datsun 710          45.6    8
# Hornet 4 Drive      42.8   12
# Hornet Sportabout   37.4   16
# Valiant             36.2   12
# Duster 360          28.6   16
# Merc 240D           48.8    8
# Merc 230            45.6    8
# ... 23 rows omitted&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;chaining&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Chaining&lt;/h2&gt;
&lt;p&gt;As a final note, it should be clear that due to the nature of &lt;code&gt;magrittr&lt;/code&gt;, your standard chaining of functions will still work.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars %&amp;gt;% 
  filter(cyl == 4) %&amp;gt;%
  select(mpg, cyl, wt, disp)
#                 mpg cyl    wt  disp
# Datsun 710     22.8   4 2.320 108.0
# Merc 240D      24.4   4 3.190 146.7
# Merc 230       22.8   4 3.150 140.8
# Fiat 128       32.4   4 2.200  78.7
# Honda Civic    30.4   4 1.615  75.7
# Toyota Corolla 33.9   4 1.835  71.1
# Toyota Corona  21.5   4 2.465 120.1
# Fiat X1-9      27.3   4 1.935  79.0
# Porsche 914-2  26.0   4 2.140 120.3
# ... 2 rows omitted&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;The idea behind this blog post was to highlight how we can use more human readable versions of R’s primitive operators to aid in pipeable data manipulation functions. Of course the solutions provided in this blog post are over-engineered and you would probably write them in a different way if you were seriously thinking about releasing them as a package. Also, whilst these functions are available via an import of &lt;code&gt;magrittr&lt;/code&gt;, you may not wish to force the user to import &lt;code&gt;magrittr&lt;/code&gt; and may wish to keep it as a suggestion instead. This reduces the number of dependencies on your package.&lt;/p&gt;
&lt;p&gt;For what it’s worth, I have included all of the above code in a package called &lt;a href=&#34;https://github.com/nathaneastwood/poorman&#34;&gt;&lt;code&gt;poorman&lt;/code&gt;&lt;/a&gt; on my GitHub account. These functions haven’t been thoroughly tested and there may well be bugs. There are, however, much more detailed and dedicated recreations of &lt;code&gt;dplyr&lt;/code&gt; using base R. If you are interested, check out: &lt;a href=&#34;https://github.com/yonicd/bplyr&#34;&gt;&lt;code&gt;bplyr&lt;/code&gt;&lt;/a&gt; (note this package uses &lt;code&gt;rlang&lt;/code&gt;) and &lt;a href=&#34;https://github.com/mkearney/tbltools&#34;&gt;&lt;code&gt;tbltools&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Primitive Functions List</title>
      <link>/2020/02/01/primitive-functions-list/</link>
      <pubDate>Sat, 01 Feb 2020 20:13:14 -0500</pubDate>
      
      <guid>/2020/02/01/primitive-functions-list/</guid>
      <description>


&lt;p&gt;Ever wondered which R functions are actually passed to internal C code? Well, wonder no more as it turns out there is an unexported named list within the &lt;code&gt;methods&lt;/code&gt; package providing instructions for turning builtin and special functions into generic functions. Wrapping this list with &lt;code&gt;names()&lt;/code&gt; gives us the list of all R functions which wrap calls to &lt;code&gt;.Primitive()&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;names(methods:::.BasicFunsList)
#   [1] &amp;quot;$&amp;quot;                    &amp;quot;$&amp;lt;-&amp;quot;                  &amp;quot;[&amp;quot;                   
#   [4] &amp;quot;[&amp;lt;-&amp;quot;                  &amp;quot;[[&amp;quot;                   &amp;quot;[[&amp;lt;-&amp;quot;                
#   [7] &amp;quot;%*%&amp;quot;                  &amp;quot;xtfrm&amp;quot;                &amp;quot;c&amp;quot;                   
#  [10] &amp;quot;all&amp;quot;                  &amp;quot;any&amp;quot;                  &amp;quot;sum&amp;quot;                 
#  [13] &amp;quot;prod&amp;quot;                 &amp;quot;max&amp;quot;                  &amp;quot;min&amp;quot;                 
#  [16] &amp;quot;range&amp;quot;                &amp;quot;is.matrix&amp;quot;            &amp;quot;&amp;gt;=&amp;quot;                  
#  [19] &amp;quot;cosh&amp;quot;                 &amp;quot;cummax&amp;quot;               &amp;quot;dimnames&amp;lt;-&amp;quot;          
#  [22] &amp;quot;as.raw&amp;quot;               &amp;quot;log2&amp;quot;                 &amp;quot;tan&amp;quot;                 
#  [25] &amp;quot;dim&amp;quot;                  &amp;quot;as.logical&amp;quot;           &amp;quot;^&amp;quot;                   
#  [28] &amp;quot;is.finite&amp;quot;            &amp;quot;sinh&amp;quot;                 &amp;quot;log10&amp;quot;               
#  [31] &amp;quot;as.numeric&amp;quot;           &amp;quot;dim&amp;lt;-&amp;quot;                &amp;quot;is.array&amp;quot;            
#  [34] &amp;quot;tanpi&amp;quot;                &amp;quot;gamma&amp;quot;                &amp;quot;atan&amp;quot;                
#  [37] &amp;quot;as.integer&amp;quot;           &amp;quot;Arg&amp;quot;                  &amp;quot;signif&amp;quot;              
#  [40] &amp;quot;cumprod&amp;quot;              &amp;quot;cos&amp;quot;                  &amp;quot;length&amp;quot;              
#  [43] &amp;quot;!=&amp;quot;                   &amp;quot;digamma&amp;quot;              &amp;quot;exp&amp;quot;                 
#  [46] &amp;quot;floor&amp;quot;                &amp;quot;acos&amp;quot;                 &amp;quot;seq.int&amp;quot;             
#  [49] &amp;quot;abs&amp;quot;                  &amp;quot;length&amp;lt;-&amp;quot;             &amp;quot;sqrt&amp;quot;                
#  [52] &amp;quot;!&amp;quot;                    &amp;quot;acosh&amp;quot;                &amp;quot;is.nan&amp;quot;              
#  [55] &amp;quot;Re&amp;quot;                   &amp;quot;tanh&amp;quot;                 &amp;quot;names&amp;quot;               
#  [58] &amp;quot;cospi&amp;quot;                &amp;quot;&amp;amp;&amp;quot;                    &amp;quot;anyNA&amp;quot;               
#  [61] &amp;quot;trunc&amp;quot;                &amp;quot;cummin&amp;quot;               &amp;quot;levels&amp;lt;-&amp;quot;            
#  [64] &amp;quot;*&amp;quot;                    &amp;quot;Mod&amp;quot;                  &amp;quot;|&amp;quot;                   
#  [67] &amp;quot;names&amp;lt;-&amp;quot;              &amp;quot;+&amp;quot;                    &amp;quot;log&amp;quot;                 
#  [70] &amp;quot;lgamma&amp;quot;               &amp;quot;as.complex&amp;quot;           &amp;quot;asinh&amp;quot;               
#  [73] &amp;quot;-&amp;quot;                    &amp;quot;sin&amp;quot;                  &amp;quot;/&amp;quot;                   
#  [76] &amp;quot;as.environment&amp;quot;       &amp;quot;&amp;lt;=&amp;quot;                   &amp;quot;as.double&amp;quot;           
#  [79] &amp;quot;is.infinite&amp;quot;          &amp;quot;is.numeric&amp;quot;           &amp;quot;rep&amp;quot;                 
#  [82] &amp;quot;round&amp;quot;                &amp;quot;sinpi&amp;quot;                &amp;quot;dimnames&amp;quot;            
#  [85] &amp;quot;asin&amp;quot;                 &amp;quot;as.character&amp;quot;         &amp;quot;%/%&amp;quot;                 
#  [88] &amp;quot;is.na&amp;quot;                &amp;quot;&amp;lt;&amp;quot;                    &amp;quot;&amp;gt;&amp;quot;                   
#  [91] &amp;quot;Im&amp;quot;                   &amp;quot;%%&amp;quot;                   &amp;quot;trigamma&amp;quot;            
#  [94] &amp;quot;==&amp;quot;                   &amp;quot;cumsum&amp;quot;               &amp;quot;atanh&amp;quot;               
#  [97] &amp;quot;sign&amp;quot;                 &amp;quot;ceiling&amp;quot;              &amp;quot;Conj&amp;quot;                
# [100] &amp;quot;as.call&amp;quot;              &amp;quot;log1p&amp;quot;                &amp;quot;expm1&amp;quot;               
# [103] &amp;quot;(&amp;quot;                    &amp;quot;:&amp;quot;                    &amp;quot;=&amp;quot;                   
# [106] &amp;quot;@&amp;quot;                    &amp;quot;{&amp;quot;                    &amp;quot;~&amp;quot;                   
# [109] &amp;quot;&amp;amp;&amp;amp;&amp;quot;                   &amp;quot;.C&amp;quot;                   &amp;quot;baseenv&amp;quot;             
# [112] &amp;quot;quote&amp;quot;                &amp;quot;&amp;lt;-&amp;quot;                   &amp;quot;is.name&amp;quot;             
# [115] &amp;quot;if&amp;quot;                   &amp;quot;||&amp;quot;                   &amp;quot;attr&amp;lt;-&amp;quot;              
# [118] &amp;quot;untracemem&amp;quot;           &amp;quot;.cache_class&amp;quot;         &amp;quot;substitute&amp;quot;          
# [121] &amp;quot;interactive&amp;quot;          &amp;quot;is.call&amp;quot;              &amp;quot;switch&amp;quot;              
# [124] &amp;quot;function&amp;quot;             &amp;quot;is.single&amp;quot;            &amp;quot;is.null&amp;quot;             
# [127] &amp;quot;is.language&amp;quot;          &amp;quot;is.pairlist&amp;quot;          &amp;quot;.External.graphics&amp;quot;  
# [130] &amp;quot;globalenv&amp;quot;            &amp;quot;class&amp;lt;-&amp;quot;              &amp;quot;.Primitive&amp;quot;          
# [133] &amp;quot;is.logical&amp;quot;           &amp;quot;enc2utf8&amp;quot;             &amp;quot;UseMethod&amp;quot;           
# [136] &amp;quot;.subset&amp;quot;              &amp;quot;proc.time&amp;quot;            &amp;quot;enc2native&amp;quot;          
# [139] &amp;quot;repeat&amp;quot;               &amp;quot;&amp;lt;&amp;lt;-&amp;quot;                  &amp;quot;@&amp;lt;-&amp;quot;                 
# [142] &amp;quot;missing&amp;quot;              &amp;quot;nargs&amp;quot;                &amp;quot;isS4&amp;quot;                
# [145] &amp;quot;.isMethodsDispatchOn&amp;quot; &amp;quot;forceAndCall&amp;quot;         &amp;quot;.primTrace&amp;quot;          
# [148] &amp;quot;storage.mode&amp;lt;-&amp;quot;       &amp;quot;.Call&amp;quot;                &amp;quot;unclass&amp;quot;             
# [151] &amp;quot;gc.time&amp;quot;              &amp;quot;.subset2&amp;quot;             &amp;quot;environment&amp;lt;-&amp;quot;       
# [154] &amp;quot;emptyenv&amp;quot;             &amp;quot;seq_len&amp;quot;              &amp;quot;.External2&amp;quot;          
# [157] &amp;quot;is.symbol&amp;quot;            &amp;quot;class&amp;quot;                &amp;quot;on.exit&amp;quot;             
# [160] &amp;quot;is.raw&amp;quot;               &amp;quot;for&amp;quot;                  &amp;quot;is.complex&amp;quot;          
# [163] &amp;quot;list&amp;quot;                 &amp;quot;invisible&amp;quot;            &amp;quot;is.character&amp;quot;        
# [166] &amp;quot;oldClass&amp;lt;-&amp;quot;           &amp;quot;is.environment&amp;quot;       &amp;quot;attributes&amp;quot;          
# [169] &amp;quot;break&amp;quot;                &amp;quot;return&amp;quot;               &amp;quot;attr&amp;quot;                
# [172] &amp;quot;tracemem&amp;quot;             &amp;quot;next&amp;quot;                 &amp;quot;.Call.graphics&amp;quot;      
# [175] &amp;quot;standardGeneric&amp;quot;      &amp;quot;is.atomic&amp;quot;            &amp;quot;retracemem&amp;quot;          
# [178] &amp;quot;expression&amp;quot;           &amp;quot;is.expression&amp;quot;        &amp;quot;call&amp;quot;                
# [181] &amp;quot;is.object&amp;quot;            &amp;quot;pos.to.env&amp;quot;           &amp;quot;attributes&amp;lt;-&amp;quot;        
# [184] &amp;quot;.primUntrace&amp;quot;         &amp;quot;...length&amp;quot;            &amp;quot;.External&amp;quot;           
# [187] &amp;quot;oldClass&amp;quot;             &amp;quot;.Internal&amp;quot;            &amp;quot;.Fortran&amp;quot;            
# [190] &amp;quot;browser&amp;quot;              &amp;quot;is.double&amp;quot;            &amp;quot;while&amp;quot;               
# [193] &amp;quot;nzchar&amp;quot;               &amp;quot;is.list&amp;quot;              &amp;quot;lazyLoadDBfetch&amp;quot;     
# [196] &amp;quot;...elt&amp;quot;               &amp;quot;is.integer&amp;quot;           &amp;quot;is.function&amp;quot;         
# [199] &amp;quot;is.recursive&amp;quot;         &amp;quot;seq_along&amp;quot;            &amp;quot;unlist&amp;quot;              
# [202] &amp;quot;as.vector&amp;quot;            &amp;quot;lengths&amp;quot;&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>Get and Set List Elements with magrittr</title>
      <link>/2020/02/01/get-and-set-list-elements-with-magrittr/</link>
      <pubDate>Sat, 01 Feb 2020 20:00:16 -0500</pubDate>
      
      <guid>/2020/02/01/get-and-set-list-elements-with-magrittr/</guid>
      <description>


&lt;div id=&#34;introduction&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Did you know that the &lt;code&gt;magrittr&lt;/code&gt; pipe, &lt;code&gt;%&amp;gt;%&lt;/code&gt;, can be used for more than just &lt;code&gt;data.frame&lt;/code&gt;s and &lt;code&gt;tibble&lt;/code&gt;s? In this blog post, we look at how we can create get and set functions for list elements.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;getting-list-elements&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Getting List Elements&lt;/h1&gt;
&lt;p&gt;First, let’s create a simple list.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;z1 &amp;lt;- list(a = pi, b = 2.718, c = 0.57721)
z1
# $a
# [1] 3.141593
# 
# $b
# [1] 2.718
# 
# $c
# [1] 0.57721&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let’s say we want to access an element of this list, typically we would use the &lt;code&gt;[[&lt;/code&gt; function to do so.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;z1[[2]]
# [1] 2.718&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But let’s say we need to access this list as part of a chain using &lt;code&gt;magrittr&lt;/code&gt;’s pipe operator, &lt;code&gt;%&amp;gt;%&lt;/code&gt;. How can we do that? Well we can pipe our list into a &lt;code&gt;.&lt;/code&gt; which acts as a placeholder for the list, on which we can perform our subset.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(magrittr)
z1 %&amp;gt;% .[[2]]
# [1] 2.718&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Another solution is to call &lt;code&gt;[[&lt;/code&gt; using its syntactic form &lt;code&gt;[[()&lt;/code&gt; using backticks (or quotes, see &lt;code&gt;?Quotes&lt;/code&gt;).&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;z1 %&amp;gt;% `[[`(2)
# [1] 2.718&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Admittedly, these two solutions don’t look very nice. So what we can do instead is assign the &lt;code&gt;[[&lt;/code&gt; function to an object which will, in effect, be a callable wrapper function.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;get &amp;lt;- .Primitive(&amp;quot;[[&amp;quot;) # Equivalent to get &amp;lt;- `[[`
get(z1, 2)
# [1] 2.718&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Primitives are functions that are internally implemented by R and so &lt;code&gt;.Primitive(&#34;[[&#34;)&lt;/code&gt; tells R to dispatch to the underlying C code, which will be able to correctly identify which &lt;code&gt;[[&lt;/code&gt; method to use on the list class (see &lt;code&gt;?.Primitive&lt;/code&gt; for more details).&lt;/p&gt;
&lt;p&gt;Since our list is now the first argument of &lt;code&gt;get()&lt;/code&gt;, we have a much “cleaner” looking way of accessing elements of a list with the &lt;code&gt;magrittr&lt;/code&gt; pipe operator than &lt;code&gt;[[&lt;/code&gt;. And so, let’s access the second element of our list using &lt;code&gt;get()&lt;/code&gt; and the &lt;code&gt;magrittr&lt;/code&gt; pipe.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;z1 %&amp;gt;% get(2)
# [1] 2.718&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can also access the list using its names, too.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;z1 %&amp;gt;% get(&amp;quot;b&amp;quot;)
# [1] 2.718&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It even works with recursive indexing!&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;z2 &amp;lt;- list(a = list(b = 9, c = &amp;quot;hello&amp;quot;), d = 1:5)
z2
# $a
# $a$b
# [1] 9
# 
# $a$c
# [1] &amp;quot;hello&amp;quot;
# 
# 
# $d
# [1] 1 2 3 4 5
z2 %&amp;gt;% get(c(&amp;quot;a&amp;quot;, &amp;quot;c&amp;quot;)) # equivalent to z %&amp;gt;% get(c(1, 2))
# [1] &amp;quot;hello&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note, you may want to choose a better name than &lt;code&gt;get&lt;/code&gt; to avoid clashes with the &lt;code&gt;base::get()&lt;/code&gt; function.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;setting-list-elements&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Setting List Elements&lt;/h1&gt;
&lt;p&gt;Similarly we can create a &lt;code&gt;set()&lt;/code&gt; function to assign values to elements of our list using &lt;code&gt;.Primitive(&#34;[[&amp;lt;-&#34;)&lt;/code&gt;. Let’s add a fourth element to our list.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;set &amp;lt;- .Primitive(&amp;quot;[[&amp;lt;-&amp;quot;)
z1 &amp;lt;- z1 %&amp;gt;% set(&amp;quot;d&amp;quot;, 4.6692)
z1
# $a
# [1] 3.141593
# 
# $b
# [1] 2.718
# 
# $c
# [1] 0.57721
# 
# $d
# [1] 4.6692&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And now just as &lt;code&gt;set()&lt;/code&gt; giveth, &lt;code&gt;set()&lt;/code&gt; taketh away.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;z1 &amp;lt;- z1 %&amp;gt;% set(&amp;quot;d&amp;quot;, NULL)
z1
# $a
# [1] 3.141593
# 
# $b
# [1] 2.718
# 
# $c
# [1] 0.57721&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Of course as this is a list, we can set any kind of data.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;z1 %&amp;gt;% set(&amp;quot;data&amp;quot;, data.frame(a = c(1, 2, 2, 4), b = c(2, 3, 7, 4)))
# $a
# [1] 3.141593
# 
# $b
# [1] 2.718
# 
# $c
# [1] 0.57721
# 
# $data
#   a b
# 1 1 2
# 2 2 3
# 3 2 7
# 4 4 4&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or even overwrite elements.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;z1 %&amp;gt;% set(&amp;quot;b&amp;quot;, 4.6692)
# $a
# [1] 3.141593
# 
# $b
# [1] 4.6692
# 
# $c
# [1] 0.57721&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;This was just a short blog post to highlight the power of &lt;code&gt;magrittr&lt;/code&gt; in combination with R primitives. We also saw how to rewrite and manipulate syntactic forms of internal R functions. What other interesting use cases have you found for the &lt;code&gt;magrittr&lt;/code&gt; pipe?&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Selecting the Max Value from Each Group, a Case Study: dplyr and sparklyr</title>
      <link>/2019/09/22/selecting-the-max-value-from-each-group-a-case-study-dplyr-and-sparklyr/</link>
      <pubDate>Sun, 22 Sep 2019 20:13:14 -0500</pubDate>
      
      <guid>/2019/09/22/selecting-the-max-value-from-each-group-a-case-study-dplyr-and-sparklyr/</guid>
      <description>
&lt;script src=&#34;/rmarkdown-libs/htmlwidgets/htmlwidgets.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/proj4js/proj4.js&#34;&gt;&lt;/script&gt;
&lt;link href=&#34;/rmarkdown-libs/highcharts/css/motion.css&#34; rel=&#34;stylesheet&#34; /&gt;
&lt;link href=&#34;/rmarkdown-libs/highcharts/css/htmlwdgtgrid.css&#34; rel=&#34;stylesheet&#34; /&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/highcharts.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/highcharts-3d.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/highcharts-more.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/stock.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/map.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/annotations.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/boost.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/data.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/drag-panes.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/drilldown.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/item-series.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/offline-exporting.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/overlapping-datalabels.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/exporting.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/export-data.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/funnel.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/heatmap.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/treemap.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/sankey.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/solid-gauge.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/streamgraph.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/sunburst.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/vector.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/wordcloud.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/xrange.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/tilemap.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/venn.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/gantt.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/timeline.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/parallel-coordinates.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/plugins/grouped-categories.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/plugins/motion.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/plugins/multicolor_series.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/custom/reset.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/custom/symbols-extra.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/custom/text-symbols.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highchart-binding/highchart.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;introduction&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;In my &lt;a href=&#34;https://nathaneastwood.github.io/2019/09/14/selecting-the-max-value-from-each-group-a-case-study-data.table/&#34;&gt;last post&lt;/a&gt; we looked at how to slice a &lt;code&gt;data.table&lt;/code&gt; by group to obtain the rows for which a particular column in that group is at its maximum value using the excellent &lt;code&gt;data.table&lt;/code&gt; package. In this post, we will be taking a look at how to perform this task using &lt;a href=&#34;https://github.com/tidyverse/dplyr&#34;&gt;&lt;code&gt;dplyr&lt;/code&gt;&lt;/a&gt; and &lt;a href=&#34;https://github.com/rstudio/sparklyr&#34;&gt;&lt;code&gt;sparklyr&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;dplyr&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;dplyr&lt;/h1&gt;
&lt;p&gt;First, let’s take a look at our data.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(dplyr)
mtcars &amp;lt;- mtcars %&amp;gt;% 
  tibble::rownames_to_column(var = &amp;quot;car&amp;quot;) %&amp;gt;% 
  tibble::as_tibble()
mtcars
# # A tibble: 32 x 12
#    car           mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#    &amp;lt;chr&amp;gt;       &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt;
#  1 Mazda RX4    21       6  160    110  3.9   2.62  16.5     0     1     4     4
#  2 Mazda RX4 …  21       6  160    110  3.9   2.88  17.0     0     1     4     4
#  3 Datsun 710   22.8     4  108     93  3.85  2.32  18.6     1     1     4     1
#  4 Hornet 4 D…  21.4     6  258    110  3.08  3.22  19.4     1     0     3     1
#  5 Hornet Spo…  18.7     8  360    175  3.15  3.44  17.0     0     0     3     2
#  6 Valiant      18.1     6  225    105  2.76  3.46  20.2     1     0     3     1
#  7 Duster 360   14.3     8  360    245  3.21  3.57  15.8     0     0     3     4
#  8 Merc 240D    24.4     4  147.    62  3.69  3.19  20       1     0     4     2
#  9 Merc 230     22.8     4  141.    95  3.92  3.15  22.9     1     0     4     2
# 10 Merc 280     19.2     6  168.   123  3.92  3.44  18.3     1     0     4     4
# # … with 22 more rows&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So here, we are interested in getting a single car from each &lt;code&gt;cyl&lt;/code&gt; group whose &lt;code&gt;mpg&lt;/code&gt; is at the maximum for that group. I really like the &lt;code&gt;dplyr&lt;/code&gt; syntax for this problem, it’s really straight forward; take a look below:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars %&amp;gt;% 
  group_by(cyl) %&amp;gt;% 
  arrange(desc(mpg)) %&amp;gt;% 
  slice(1) %&amp;gt;% 
  ungroup()
# # A tibble: 3 x 12
#   car            mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#   &amp;lt;chr&amp;gt;        &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt;
# 1 Toyota Coro…  33.9     4  71.1    65  4.22  1.84  19.9     1     1     4     1
# 2 Hornet 4 Dr…  21.4     6 258     110  3.08  3.22  19.4     1     0     3     1
# 3 Pontiac Fir…  19.2     8 400     175  3.08  3.84  17.0     0     0     3     2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We tell &lt;code&gt;dplyr&lt;/code&gt; to create groups of data for each of the &lt;code&gt;cyl&lt;/code&gt; levels and then within each group we &lt;code&gt;arrange()&lt;/code&gt; by &lt;code&gt;mpg&lt;/code&gt; in descending order. Once we have our data organised in this way it’s as simple as taking the top row from each group using &lt;code&gt;slice()&lt;/code&gt;. Of course there is more than one way we can achieve this task using &lt;code&gt;dplyr&lt;/code&gt;, take this next example for instance.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars %&amp;gt;% 
  group_by(cyl) %&amp;gt;% 
  arrange(desc(mpg)) %&amp;gt;% 
  mutate(row_number = row_number()) %&amp;gt;% 
  filter(row_number == 1) %&amp;gt;% 
  select(-row_number) %&amp;gt;% 
  ungroup()
# # A tibble: 3 x 12
#   car            mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#   &amp;lt;chr&amp;gt;        &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt;
# 1 Toyota Coro…  33.9     4  71.1    65  4.22  1.84  19.9     1     1     4     1
# 2 Hornet 4 Dr…  21.4     6 258     110  3.08  3.22  19.4     1     0     3     1
# 3 Pontiac Fir…  19.2     8 400     175  3.08  3.84  17.0     0     0     3     2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It might not seem to be the most logical approach to this problem given we have access to the &lt;code&gt;slice()&lt;/code&gt; function but it feeds nicely into the &lt;a href=&#34;#sparklyr&#34;&gt;&lt;code&gt;sparklyr&lt;/code&gt;&lt;/a&gt; section.&lt;/p&gt;
&lt;p&gt;If you are interested, below you can see the benchmarks for these two &lt;code&gt;dplyr&lt;/code&gt; approaches. We can see that the &lt;code&gt;slice()&lt;/code&gt; approach is much quicker than the &lt;code&gt;mutate()&lt;/code&gt; approach which we would expect since there is much less manipulation of the data going on in the first approach.&lt;/p&gt;
&lt;div id=&#34;htmlwidget-1&#34; style=&#34;width:100%;height:500px;&#34; class=&#34;highchart html-widget&#34;&gt;&lt;/div&gt;
&lt;script type=&#34;application/json&#34; data-for=&#34;htmlwidget-1&#34;&gt;{&#34;x&#34;:{&#34;hc_opts&#34;:{&#34;title&#34;:{&#34;text&#34;:&#34;&lt;b&gt;data.table Solutions&lt;b&gt;&#34;},&#34;yAxis&#34;:{&#34;title&#34;:{&#34;text&#34;:&#34;&lt;b&gt; Time (ns)&lt;b&gt;&#34;}},&#34;credits&#34;:{&#34;enabled&#34;:false},&#34;exporting&#34;:{&#34;enabled&#34;:false},&#34;plotOptions&#34;:{&#34;series&#34;:{&#34;label&#34;:{&#34;enabled&#34;:false},&#34;turboThreshold&#34;:0,&#34;marker&#34;:{&#34;symbol&#34;:&#34;circle&#34;},&#34;showInLegend&#34;:false},&#34;treemap&#34;:{&#34;layoutAlgorithm&#34;:&#34;squarified&#34;}},&#34;chart&#34;:{&#34;type&#34;:&#34;column&#34;},&#34;xAxis&#34;:{&#34;type&#34;:&#34;category&#34;,&#34;categories&#34;:&#34;&#34;},&#34;series&#34;:[{&#34;g2&#34;:null,&#34;data&#34;:[{&#34;name&#34;:&#34;slice&#34;,&#34;low&#34;:618012,&#34;q1&#34;:633643,&#34;median&#34;:647378.5,&#34;q3&#34;:784681.5,&#34;high&#34;:888473},{&#34;name&#34;:&#34;mutate&#34;,&#34;low&#34;:1567024,&#34;q1&#34;:1601592.5,&#34;median&#34;:1655655.5,&#34;q3&#34;:1982287.5,&#34;high&#34;:2232860}],&#34;type&#34;:&#34;boxplot&#34;,&#34;id&#34;:null,&#34;name&#34;:&#34;Solution&#34;,&#34;color&#34;:&#34;#6272a4&#34;,&#34;fillColor&#34;:&#34;#f8f8f2&#34;,&#34;lineWidth&#34;:1.5}]},&#34;theme&#34;:{&#34;chart&#34;:{&#34;backgroundColor&#34;:&#34;transparent&#34;}},&#34;conf_opts&#34;:{&#34;global&#34;:{&#34;Date&#34;:null,&#34;VMLRadialGradientURL&#34;:&#34;http =//code.highcharts.com/list(version)/gfx/vml-radial-gradient.png&#34;,&#34;canvasToolsURL&#34;:&#34;http =//code.highcharts.com/list(version)/modules/canvas-tools.js&#34;,&#34;getTimezoneOffset&#34;:null,&#34;timezoneOffset&#34;:0,&#34;useUTC&#34;:true},&#34;lang&#34;:{&#34;contextButtonTitle&#34;:&#34;Chart context menu&#34;,&#34;decimalPoint&#34;:&#34;.&#34;,&#34;downloadJPEG&#34;:&#34;Download JPEG image&#34;,&#34;downloadPDF&#34;:&#34;Download PDF document&#34;,&#34;downloadPNG&#34;:&#34;Download PNG image&#34;,&#34;downloadSVG&#34;:&#34;Download SVG vector image&#34;,&#34;drillUpText&#34;:&#34;Back to {series.name}&#34;,&#34;invalidDate&#34;:null,&#34;loading&#34;:&#34;Loading...&#34;,&#34;months&#34;:[&#34;January&#34;,&#34;February&#34;,&#34;March&#34;,&#34;April&#34;,&#34;May&#34;,&#34;June&#34;,&#34;July&#34;,&#34;August&#34;,&#34;September&#34;,&#34;October&#34;,&#34;November&#34;,&#34;December&#34;],&#34;noData&#34;:&#34;No data to display&#34;,&#34;numericSymbols&#34;:[&#34;k&#34;,&#34;M&#34;,&#34;G&#34;,&#34;T&#34;,&#34;P&#34;,&#34;E&#34;],&#34;printChart&#34;:&#34;Print chart&#34;,&#34;resetZoom&#34;:&#34;Reset zoom&#34;,&#34;resetZoomTitle&#34;:&#34;Reset zoom level 1:1&#34;,&#34;shortMonths&#34;:[&#34;Jan&#34;,&#34;Feb&#34;,&#34;Mar&#34;,&#34;Apr&#34;,&#34;May&#34;,&#34;Jun&#34;,&#34;Jul&#34;,&#34;Aug&#34;,&#34;Sep&#34;,&#34;Oct&#34;,&#34;Nov&#34;,&#34;Dec&#34;],&#34;thousandsSep&#34;:&#34; &#34;,&#34;weekdays&#34;:[&#34;Sunday&#34;,&#34;Monday&#34;,&#34;Tuesday&#34;,&#34;Wednesday&#34;,&#34;Thursday&#34;,&#34;Friday&#34;,&#34;Saturday&#34;]}},&#34;type&#34;:&#34;chart&#34;,&#34;fonts&#34;:[],&#34;debug&#34;:false},&#34;evals&#34;:[],&#34;jsHooks&#34;:[]}&lt;/script&gt;
&lt;/div&gt;
&lt;div id=&#34;sparklyr&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;&lt;code&gt;sparklyr&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;A great feature of &lt;code&gt;dplyr&lt;/code&gt; is its ability to execute your R code on a Spark cluster. To achieve this, &lt;code&gt;dplyr&lt;/code&gt; uses the &lt;a href=&#34;https://github.com/tidyverse/dbplyr&#34;&gt;&lt;code&gt;dbplyr&lt;/code&gt;&lt;/a&gt; package which translates your &lt;code&gt;dplyr&lt;/code&gt; code into Spark SQL code which can then be passed to the Spark connection to be executed by your Spark cluster. The problem, however, is that not all &lt;code&gt;dplyr&lt;/code&gt; verbs translate.&lt;/p&gt;
&lt;p&gt;First, let’s set up a local Spark cluster and upload the &lt;code&gt;mtcars&lt;/code&gt; data to it.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(sparklyr)
sc &amp;lt;- spark_connect(master = &amp;quot;local&amp;quot;)
mtcars_spark &amp;lt;- copy_to(sc, mtcars, &amp;quot;mtcars&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can explore our first &lt;code&gt;dplyr&lt;/code&gt; example by attempting to execute it on the Spark cluster. We use &lt;code&gt;dbplyr::sql_render()&lt;/code&gt; as the final part of the chain to try and see the SQL code that &lt;code&gt;dbplyr&lt;/code&gt; translates the &lt;code&gt;dplyr&lt;/code&gt; code to.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars_spark %&amp;gt;% 
  group_by(cyl) %&amp;gt;% 
  arrange(desc(mpg)) %&amp;gt;% 
  slice(1) %&amp;gt;% 
  ungroup() %&amp;gt;% 
  dbplyr::sql_render()
# Error in slice_.tbl_spark(.data, .dots = compat_as_lazy_dots(...)): Slice is not supported in this version of sparklyr&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this instance, &lt;code&gt;dplyr&lt;/code&gt; tells us that we cannot use &lt;code&gt;slice()&lt;/code&gt; since it is not currently supported by &lt;code&gt;sparklyr&lt;/code&gt;, this is because there is no direct translation from &lt;code&gt;slice()&lt;/code&gt; to Spark SQL code. So let’s try our second approach.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars_spark %&amp;gt;% 
  group_by(cyl) %&amp;gt;% 
  arrange(desc(mpg)) %&amp;gt;% 
  mutate(row_number = row_number()) %&amp;gt;% 
  filter(row_number == 1) %&amp;gt;% 
  select(-row_number) %&amp;gt;% 
  ungroup() %&amp;gt;% 
  dbplyr::sql_render()
# &amp;lt;SQL&amp;gt; SELECT `car`, `mpg`, `cyl`, `disp`, `hp`, `drat`, `wt`, `qsec`, `vs`, `am`, `gear`, `carb`
# FROM (SELECT `car`, `mpg`, `cyl`, `disp`, `hp`, `drat`, `wt`, `qsec`, `vs`, `am`, `gear`, `carb`, ROW_NUMBER() OVER (PARTITION BY `cyl` ORDER BY `mpg` DESC) AS `row_number`
# FROM (SELECT *
# FROM `mtcars`
# ORDER BY `mpg` DESC) `dbplyr_001`) `dbplyr_002`
# WHERE (`row_number` = 1.0)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here we see that the function &lt;code&gt;row_number()&lt;/code&gt; does translate; since it is a ranking function which mimics the functions described in SQL2003 (see &lt;code&gt;?ranking&lt;/code&gt;), &lt;code&gt;dbplyr&lt;/code&gt; knows the equivalent SQL code.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars_spark %&amp;gt;% 
  group_by(cyl) %&amp;gt;% 
  arrange(desc(mpg)) %&amp;gt;% 
  mutate(row_number = row_number()) %&amp;gt;% 
  filter(row_number == 1) %&amp;gt;% 
  select(-row_number) %&amp;gt;% 
  ungroup() %&amp;gt;% 
  collect()
# # A tibble: 3 x 12
#   car            mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#   &amp;lt;chr&amp;gt;        &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt;
# 1 Hornet 4 Dr…  21.4     6 258     110  3.08  3.22  19.4     1     0     3     1
# 2 Toyota Coro…  33.9     4  71.1    65  4.22  1.84  19.9     1     1     4     1
# 3 Pontiac Fir…  19.2     8 400     175  3.08  3.84  17.0     0     0     3     2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So really when it comes to using &lt;code&gt;dplyr&lt;/code&gt; for data manipulation in Spark it sometimes requires some persistence in finding a function which will translate nicely to Spark SQL, especially if you don’t want to use the often slow &lt;code&gt;spark_apply()&lt;/code&gt; function to apply an R function to a Spark object. Although I would recommend reading the &lt;a href=&#34;https://spark.rstudio.com/dplyr/&#34;&gt;&lt;code&gt;sparklyr&lt;/code&gt; documentation&lt;/a&gt;, it can often be a little light on the details and so for a more detailed look at how to send R code to be executed on your Spark cluster, check out my colleague Jozef’s &lt;a href=&#34;https://jozef.io/r201-spark-r-1/#an-r-function-translated-to-spark-sql&#34;&gt;blog post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As a side note, should you not be able to find an R function which will translate to SQL code, it is always worth checking out the list of &lt;a href=&#34;https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF&#34;&gt;Hive Operators and User-Defined Functions (UDFs)&lt;/a&gt;. UDFs are functions that are built for specific purposes to perform operations like Mathematical, arithmetic, logical and relational on the operands of table column names.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;This concludes this series of blog posts in which we have seen how we can select a single row from a &lt;code&gt;data.frame&lt;/code&gt;, &lt;code&gt;data.table&lt;/code&gt; or &lt;code&gt;tibble&lt;/code&gt; for each group, where a column in that group is at the maximum value for its group. In this post, we saw how this task is quite easy to do with &lt;code&gt;dplyr&lt;/code&gt;’s &lt;code&gt;group_by()&lt;/code&gt; and &lt;code&gt;slice()&lt;/code&gt; combination of functions. We then saw how we can translate our &lt;code&gt;dplyr&lt;/code&gt; code to be executed as SQL code on a Spark cluster; though not all &lt;code&gt;dplyr&lt;/code&gt; “verbs” currently translate into SQL. To that end, it is often worth looking to see if there is a Hive User-Defined Function to perform the data manipulation task at hand if there is not a direct translation of a &lt;code&gt;dplyr&lt;/code&gt; function.&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Selecting the Max Value from Each Group, a Case Study: data.table</title>
      <link>/2019/09/14/selecting-the-max-value-from-each-group-a-case-study-data.table/</link>
      <pubDate>Sat, 14 Sep 2019 19:13:14 -0500</pubDate>
      
      <guid>/2019/09/14/selecting-the-max-value-from-each-group-a-case-study-data.table/</guid>
      <description>
&lt;script src=&#34;/rmarkdown-libs/htmlwidgets/htmlwidgets.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/proj4js/proj4.js&#34;&gt;&lt;/script&gt;
&lt;link href=&#34;/rmarkdown-libs/highcharts/css/motion.css&#34; rel=&#34;stylesheet&#34; /&gt;
&lt;link href=&#34;/rmarkdown-libs/highcharts/css/htmlwdgtgrid.css&#34; rel=&#34;stylesheet&#34; /&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/highcharts.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/highcharts-3d.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/highcharts-more.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/stock.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/map.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/annotations.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/boost.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/data.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/drag-panes.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/drilldown.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/item-series.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/offline-exporting.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/overlapping-datalabels.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/exporting.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/export-data.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/funnel.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/heatmap.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/treemap.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/sankey.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/solid-gauge.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/streamgraph.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/sunburst.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/vector.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/wordcloud.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/xrange.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/tilemap.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/venn.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/gantt.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/timeline.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/parallel-coordinates.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/plugins/grouped-categories.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/plugins/motion.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/plugins/multicolor_series.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/custom/reset.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/custom/symbols-extra.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/custom/text-symbols.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highchart-binding/highchart.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;introduction&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;In my &lt;a href=&#34;https://nathaneastwood.github.io/2019/09/14/selecting-the-max-value-from-each-group-a-case-study-base-r/&#34;&gt;last post&lt;/a&gt; we looked at how to slice a &lt;code&gt;data.frame&lt;/code&gt; by group to obtain the rows for which a particular column in that group is at its maximum value using base R. In this post, we will be taking a look at how to perform this task using &lt;a href=&#34;https://github.com/Rdatatable/data.table&#34;&gt;&lt;code&gt;data.table&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;data.table-solutions&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;&lt;code&gt;data.table&lt;/code&gt; Solution(s)&lt;/h1&gt;
&lt;p&gt;For this exercise we will be using &lt;code&gt;datasets::mtcars&lt;/code&gt; and so first, we must convert &lt;code&gt;mtcars&lt;/code&gt; to a &lt;code&gt;data.table&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(data.table)
mtcars &amp;lt;- as.data.table(mtcars, keep.rownames = &amp;quot;car&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The current &lt;code&gt;data.table&lt;/code&gt; syntax suggests that when grouping data, we should use the &lt;code&gt;.SD&lt;/code&gt; syntax. &lt;code&gt;.SD&lt;/code&gt; stands for “&lt;code&gt;S&lt;/code&gt;ubset of &lt;code&gt;D&lt;/code&gt;ata.table”, so when we group the data &lt;code&gt;by&lt;/code&gt; a variable, we are creating subsets of the data. Note that there’s &lt;a href=&#34;https://stackoverflow.com/a/8509301/3759418&#34;&gt;no significance&lt;/a&gt; to the initial &lt;code&gt;.&lt;/code&gt;, except that it makes it slightly more unlikely that there will be a clash with a user-defined column name. So, one approach to solving our problem can be seen below.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars[, .SD[which.max(mpg)], by = cyl]
#    cyl              car  mpg  disp  hp drat    wt  qsec vs am gear carb
# 1:   6   Hornet 4 Drive 21.4 258.0 110 3.08 3.215 19.44  1  0    3    1
# 2:   4   Toyota Corolla 33.9  71.1  65 4.22 1.835 19.90  1  1    4    1
# 3:   8 Pontiac Firebird 19.2 400.0 175 3.08 3.845 17.05  0  0    3    2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So this code essentially treats &lt;code&gt;.SD&lt;/code&gt; as a “group”, one for each cylinder level (&lt;code&gt;by&lt;/code&gt;), and subsets the row by the index where &lt;code&gt;mpg&lt;/code&gt; is at its maximum.&lt;/p&gt;
&lt;p&gt;However this wasn’t always the case with &lt;code&gt;data.table&lt;/code&gt;, there is some legacy syntax which is still valid within the package. If we take a look at the following code, we will see that we can obtain the row where &lt;code&gt;mpg&lt;/code&gt; is at its maximum using the &lt;code&gt;.I&lt;/code&gt; syntax.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars[, .I[which.max(mpg)]]
# [1] 20&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In other words, here &lt;code&gt;.I&lt;/code&gt; is a vector representing the row number where &lt;code&gt;mpg&lt;/code&gt; is at its maximum in the original &lt;code&gt;data.table&lt;/code&gt;. Now consider the case where we look at this by each cylinder group; we obtain a &lt;code&gt;data.table&lt;/code&gt; whose column &lt;code&gt;V1&lt;/code&gt; represents the row indices for each cylinder group where &lt;code&gt;mpg&lt;/code&gt; is at its maximum, i.e. one row for each group.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars[, .I[which.max(mpg)], by = cyl]
#    cyl V1
# 1:   6  4
# 2:   4 20
# 3:   8 25&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So using this &lt;code&gt;data.table&lt;/code&gt; we can subset on the column &lt;code&gt;V1&lt;/code&gt; to extract these row indices and subset the original &lt;code&gt;data.table&lt;/code&gt; for those rows.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars[mtcars[, .I[which.max(mpg)], by = cyl]$V1]
#                 car  mpg cyl  disp  hp drat    wt  qsec vs am gear carb
# 1:   Hornet 4 Drive 21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
# 2:   Toyota Corolla 33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
# 3: Pontiac Firebird 19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The final way in which we could solve this problem with &lt;code&gt;data.table&lt;/code&gt; is in fact very similar to the base R approach that we saw in the previous post. This involves &lt;code&gt;split&lt;/code&gt;ting the &lt;code&gt;data.table&lt;/code&gt; into three separate &lt;code&gt;data.table&lt;/code&gt;s, one for each cylinder group, and applying a function to each group that finds the index of the maximum row, subsetting the grouped &lt;code&gt;data.table&lt;/code&gt; on that index. We then bind these lists together using the &lt;code&gt;data.table::rbindlist()&lt;/code&gt; function. In fact, we could have even used the &lt;code&gt;do.call(rbind, .)&lt;/code&gt; approach we saw in the first post.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;rbindlist(lapply(split(mtcars, mtcars[, cyl]), function(x) x[which.max(mpg)]))
#                 car  mpg cyl  disp  hp drat    wt  qsec vs am gear carb
# 1:   Toyota Corolla 33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
# 2:   Hornet 4 Drive 21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
# 3: Pontiac Firebird 19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So there we have it, three separate ways to solve the same problem using &lt;code&gt;data.table&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;benchmarks&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Benchmarks&lt;/h1&gt;
&lt;p&gt;Now this wouldn’t be a completely informative blog post without some benchmarks. In fact these three options are what inspired me to write this series of posts. We can see the results of the benchmarking below.&lt;/p&gt;
&lt;div id=&#34;htmlwidget-1&#34; style=&#34;width:100%;height:500px;&#34; class=&#34;highchart html-widget&#34;&gt;&lt;/div&gt;
&lt;script type=&#34;application/json&#34; data-for=&#34;htmlwidget-1&#34;&gt;{&#34;x&#34;:{&#34;hc_opts&#34;:{&#34;title&#34;:{&#34;text&#34;:&#34;&lt;b&gt;data.table Solutions&lt;b&gt;&#34;},&#34;yAxis&#34;:{&#34;title&#34;:{&#34;text&#34;:&#34;&lt;b&gt; Time (ns)&lt;b&gt;&#34;}},&#34;credits&#34;:{&#34;enabled&#34;:false},&#34;exporting&#34;:{&#34;enabled&#34;:false},&#34;plotOptions&#34;:{&#34;series&#34;:{&#34;label&#34;:{&#34;enabled&#34;:false},&#34;turboThreshold&#34;:0,&#34;marker&#34;:{&#34;symbol&#34;:&#34;circle&#34;},&#34;showInLegend&#34;:false},&#34;treemap&#34;:{&#34;layoutAlgorithm&#34;:&#34;squarified&#34;}},&#34;chart&#34;:{&#34;type&#34;:&#34;column&#34;},&#34;xAxis&#34;:{&#34;type&#34;:&#34;category&#34;,&#34;categories&#34;:&#34;&#34;},&#34;series&#34;:[{&#34;g2&#34;:null,&#34;data&#34;:[{&#34;name&#34;:&#34;.SD&#34;,&#34;low&#34;:609765,&#34;q1&#34;:672803,&#34;median&#34;:780947,&#34;q3&#34;:908894,&#34;high&#34;:1176229},{&#34;name&#34;:&#34;.I&#34;,&#34;low&#34;:424729,&#34;q1&#34;:472479.5,&#34;median&#34;:536495,&#34;q3&#34;:606264,&#34;high&#34;:785185},{&#34;name&#34;:&#34;rbindlist&#34;,&#34;low&#34;:1013911,&#34;q1&#34;:1114113.5,&#34;median&#34;:1327455.5,&#34;q3&#34;:1592234,&#34;high&#34;:2192359}],&#34;type&#34;:&#34;boxplot&#34;,&#34;id&#34;:null,&#34;name&#34;:&#34;Solution&#34;,&#34;color&#34;:&#34;#6272a4&#34;,&#34;fillColor&#34;:&#34;#f8f8f2&#34;,&#34;lineWidth&#34;:1.5}]},&#34;theme&#34;:{&#34;chart&#34;:{&#34;backgroundColor&#34;:&#34;transparent&#34;}},&#34;conf_opts&#34;:{&#34;global&#34;:{&#34;Date&#34;:null,&#34;VMLRadialGradientURL&#34;:&#34;http =//code.highcharts.com/list(version)/gfx/vml-radial-gradient.png&#34;,&#34;canvasToolsURL&#34;:&#34;http =//code.highcharts.com/list(version)/modules/canvas-tools.js&#34;,&#34;getTimezoneOffset&#34;:null,&#34;timezoneOffset&#34;:0,&#34;useUTC&#34;:true},&#34;lang&#34;:{&#34;contextButtonTitle&#34;:&#34;Chart context menu&#34;,&#34;decimalPoint&#34;:&#34;.&#34;,&#34;downloadJPEG&#34;:&#34;Download JPEG image&#34;,&#34;downloadPDF&#34;:&#34;Download PDF document&#34;,&#34;downloadPNG&#34;:&#34;Download PNG image&#34;,&#34;downloadSVG&#34;:&#34;Download SVG vector image&#34;,&#34;drillUpText&#34;:&#34;Back to {series.name}&#34;,&#34;invalidDate&#34;:null,&#34;loading&#34;:&#34;Loading...&#34;,&#34;months&#34;:[&#34;January&#34;,&#34;February&#34;,&#34;March&#34;,&#34;April&#34;,&#34;May&#34;,&#34;June&#34;,&#34;July&#34;,&#34;August&#34;,&#34;September&#34;,&#34;October&#34;,&#34;November&#34;,&#34;December&#34;],&#34;noData&#34;:&#34;No data to display&#34;,&#34;numericSymbols&#34;:[&#34;k&#34;,&#34;M&#34;,&#34;G&#34;,&#34;T&#34;,&#34;P&#34;,&#34;E&#34;],&#34;printChart&#34;:&#34;Print chart&#34;,&#34;resetZoom&#34;:&#34;Reset zoom&#34;,&#34;resetZoomTitle&#34;:&#34;Reset zoom level 1:1&#34;,&#34;shortMonths&#34;:[&#34;Jan&#34;,&#34;Feb&#34;,&#34;Mar&#34;,&#34;Apr&#34;,&#34;May&#34;,&#34;Jun&#34;,&#34;Jul&#34;,&#34;Aug&#34;,&#34;Sep&#34;,&#34;Oct&#34;,&#34;Nov&#34;,&#34;Dec&#34;],&#34;thousandsSep&#34;:&#34; &#34;,&#34;weekdays&#34;:[&#34;Sunday&#34;,&#34;Monday&#34;,&#34;Tuesday&#34;,&#34;Wednesday&#34;,&#34;Thursday&#34;,&#34;Friday&#34;,&#34;Saturday&#34;]}},&#34;type&#34;:&#34;chart&#34;,&#34;fonts&#34;:[],&#34;debug&#34;:false},&#34;evals&#34;:[],&#34;jsHooks&#34;:[]}&lt;/script&gt;
&lt;p&gt;We can see that, on average, the &lt;code&gt;.I&lt;/code&gt; solution is fastest. So you may be wondering, if the &lt;code&gt;.SD&lt;/code&gt; syntax is the newer syntax, why then is the &lt;code&gt;.I&lt;/code&gt; code quicker? Well it’s simply because &lt;code&gt;.SD&lt;/code&gt; has &lt;a href=&#34;https://github.com/Rdatatable/data.table/issues/735&#34;&gt;not yet been completely optimised&lt;/a&gt;. &lt;code&gt;.I&lt;/code&gt; avoids constructing &lt;code&gt;.SD&lt;/code&gt;, which is the bottleneck in the &lt;code&gt;.SD&lt;/code&gt; solution.&lt;/p&gt;
&lt;p&gt;As a side note, we could speed these results up even more with &lt;code&gt;data.table::setkey(mtcars, cyl)&lt;/code&gt;. I won’t show the benchmarking results here as the data is so small it isn’t really a useful representation but it is worth considering should you need to perform a similar task on a larger dataset.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;If you need to apply some function to each group within a &lt;code&gt;data.table&lt;/code&gt;, &lt;code&gt;data.table&lt;/code&gt; has many solutions. The newest solution, &lt;code&gt;.SD&lt;/code&gt;, may not always be the fastest approach and you should try the old &lt;code&gt;.I&lt;/code&gt; approach if speed is important.&lt;/p&gt;
&lt;p&gt;Are you aware of any other &lt;code&gt;data.table&lt;/code&gt; solutions to this problem? If so, let me know in the comments!&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://nathaneastwood.github.io/2019/09/14/selecting-the-max-value-from-each-group-a-case-study-dplyr-and-sparklyr/&#34;&gt;Next time&lt;/a&gt;, we will take a look at how to solve this problem in &lt;code&gt;dplyr&lt;/code&gt; as well as &lt;code&gt;sparklyr&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Selecting the Max Value from Each Group, a Case Study: base R</title>
      <link>/2019/09/14/selecting-the-max-value-from-each-group-a-case-study-base-r/</link>
      <pubDate>Sat, 14 Sep 2019 18:13:14 -0500</pubDate>
      
      <guid>/2019/09/14/selecting-the-max-value-from-each-group-a-case-study-base-r/</guid>
      <description>
&lt;script src=&#34;/rmarkdown-libs/htmlwidgets/htmlwidgets.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/proj4js/proj4.js&#34;&gt;&lt;/script&gt;
&lt;link href=&#34;/rmarkdown-libs/highcharts/css/motion.css&#34; rel=&#34;stylesheet&#34; /&gt;
&lt;link href=&#34;/rmarkdown-libs/highcharts/css/htmlwdgtgrid.css&#34; rel=&#34;stylesheet&#34; /&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/highcharts.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/highcharts-3d.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/highcharts-more.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/stock.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/map.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/annotations.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/boost.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/data.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/drag-panes.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/drilldown.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/item-series.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/offline-exporting.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/overlapping-datalabels.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/exporting.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/export-data.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/funnel.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/heatmap.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/treemap.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/sankey.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/solid-gauge.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/streamgraph.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/sunburst.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/vector.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/wordcloud.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/xrange.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/tilemap.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/venn.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/gantt.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/timeline.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/modules/parallel-coordinates.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/plugins/grouped-categories.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/plugins/motion.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/plugins/multicolor_series.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/custom/reset.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/custom/symbols-extra.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highcharts/custom/text-symbols.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;/rmarkdown-libs/highchart-binding/highchart.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;introduction&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Let’s say we wish to group some data by a variable, then for each group we wish to find the row of the maximum value of another variable, and then finally extract the entire row. This is a fairly common task and in fact I’ve had to do this exact data exploration technique on several occasions in the last week using different syntax, &lt;code&gt;data.table&lt;/code&gt; and &lt;code&gt;sparklyr&lt;/code&gt;; so I thought I would share my code with you so you can compare the different options. In fact for this blog entry, I will be using base R before looking at &lt;code&gt;data.table&lt;/code&gt;, &lt;code&gt;dplyr&lt;/code&gt; and &lt;code&gt;sparklyr&lt;/code&gt; in subsequent posts.&lt;/p&gt;
&lt;p&gt;For this exercise, I will be using the classic &lt;code&gt;datasets::mtcars&lt;/code&gt; data. The aim here is to find the row for each cylinder group (&lt;code&gt;cyl&lt;/code&gt;) where the miles per gallon (&lt;code&gt;mpg&lt;/code&gt;) value is at its highest. I am not interested in finding multiple rows, I just want one row for each group even if there are cars which share the same &lt;code&gt;mpg&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;base-r-solution&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Base R Solution&lt;/h1&gt;
&lt;p&gt;For this blog entry, I am going to look at using base R. This is a classic &lt;code&gt;split()&lt;/code&gt; + &lt;code&gt;lapply()&lt;/code&gt; problem. First I’ll do some pre-processing to &lt;code&gt;mtcars&lt;/code&gt; just so that we can see which cars have the maximum mpg for each cylinder group.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Create a column of car names
mtcars_colnames &amp;lt;- colnames(mtcars)
mtcars[, &amp;quot;car&amp;quot;] &amp;lt;- rownames(mtcars)
mtcars &amp;lt;- mtcars[, c(&amp;quot;car&amp;quot;, mtcars_colnames)]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can find the rows we want.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;max_mpg &amp;lt;- do.call(rbind, lapply(
  # Split the data into groups for each cylinder
  split(mtcars, mtcars[, &amp;quot;cyl&amp;quot;]),
  function(x) {
    # For the group `x`, select the row which has the maximum mpg
    x[which.max(x[, &amp;quot;mpg&amp;quot;]), ]
  }
))
rownames(max_mpg) &amp;lt;- NULL
max_mpg
#                car  mpg cyl  disp  hp drat    wt  qsec vs am gear carb
# 1   Toyota Corolla 33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
# 2   Hornet 4 Drive 21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
# 3 Pontiac Firebird 19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So what we did here is &lt;code&gt;split()&lt;/code&gt; the &lt;code&gt;data.frame&lt;/code&gt; into separate lists, one for each cylinder group, and then used &lt;code&gt;lapply()&lt;/code&gt; (list apply) to apply a function which, for each group, selects the row which has the maximum mpg. Finally we &lt;code&gt;rbind()&lt;/code&gt; each list back together into a &lt;code&gt;data.frame&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You may be curious about my use of &lt;code&gt;which.max(x[, &#34;mpg&#34;])&lt;/code&gt; over say &lt;code&gt;mtcars[mtcars$mpg == max(mtcars$mpg), ]&lt;/code&gt;, well it’s because the former will only return a single row, whereas the latter will return multiple matching rows (check out &lt;code&gt;?which.max&lt;/code&gt;) and in this instance I was only interested in a single row for each group.&lt;/p&gt;
&lt;p&gt;Another approach for base R is to use the &lt;code&gt;by&lt;/code&gt; function.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;do.call(rbind, by(datasets::mtcars, mtcars$cyl, function(x) x[which.max(x$mpg), ]))
#    mpg cyl  disp  hp drat    wt  qsec vs am gear carb
# 4 33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
# 6 21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
# 8 19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This acts in a similar way to the &lt;code&gt;split&lt;/code&gt; + &lt;code&gt;lapply&lt;/code&gt; approach in that the &lt;code&gt;data.frame&lt;/code&gt; is split by row into &lt;code&gt;data.frame&lt;/code&gt;s subset by the values of one or more factors, in this case &lt;code&gt;cyl&lt;/code&gt;, and a function is then applied to each subset in turn. However as we can see from the benchmarks below, it isn’t quite as fast (in this case) as the former approach.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;benchmarks&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Benchmarks&lt;/h1&gt;
&lt;div id=&#34;htmlwidget-1&#34; style=&#34;width:100%;height:500px;&#34; class=&#34;highchart html-widget&#34;&gt;&lt;/div&gt;
&lt;script type=&#34;application/json&#34; data-for=&#34;htmlwidget-1&#34;&gt;{&#34;x&#34;:{&#34;hc_opts&#34;:{&#34;title&#34;:{&#34;text&#34;:&#34;&lt;b&gt;data.table Solutions&lt;b&gt;&#34;},&#34;yAxis&#34;:{&#34;title&#34;:{&#34;text&#34;:&#34;&lt;b&gt; Time (ns)&lt;b&gt;&#34;}},&#34;credits&#34;:{&#34;enabled&#34;:false},&#34;exporting&#34;:{&#34;enabled&#34;:false},&#34;plotOptions&#34;:{&#34;series&#34;:{&#34;label&#34;:{&#34;enabled&#34;:false},&#34;turboThreshold&#34;:0,&#34;marker&#34;:{&#34;symbol&#34;:&#34;circle&#34;},&#34;showInLegend&#34;:false},&#34;treemap&#34;:{&#34;layoutAlgorithm&#34;:&#34;squarified&#34;}},&#34;chart&#34;:{&#34;type&#34;:&#34;column&#34;},&#34;xAxis&#34;:{&#34;type&#34;:&#34;category&#34;,&#34;categories&#34;:&#34;&#34;},&#34;series&#34;:[{&#34;g2&#34;:null,&#34;data&#34;:[{&#34;name&#34;:&#34;split_lapply&#34;,&#34;low&#34;:896684,&#34;q1&#34;:937438,&#34;median&#34;:969807,&#34;q3&#34;:1014800.5,&#34;high&#34;:1099156},{&#34;name&#34;:&#34;by&#34;,&#34;low&#34;:928537,&#34;q1&#34;:968404,&#34;median&#34;:996567.5,&#34;q3&#34;:1047470,&#34;high&#34;:1145391}],&#34;type&#34;:&#34;boxplot&#34;,&#34;id&#34;:null,&#34;name&#34;:&#34;Solution&#34;,&#34;color&#34;:&#34;#6272a4&#34;,&#34;fillColor&#34;:&#34;#f8f8f2&#34;,&#34;lineWidth&#34;:1.5}]},&#34;theme&#34;:{&#34;chart&#34;:{&#34;backgroundColor&#34;:&#34;transparent&#34;}},&#34;conf_opts&#34;:{&#34;global&#34;:{&#34;Date&#34;:null,&#34;VMLRadialGradientURL&#34;:&#34;http =//code.highcharts.com/list(version)/gfx/vml-radial-gradient.png&#34;,&#34;canvasToolsURL&#34;:&#34;http =//code.highcharts.com/list(version)/modules/canvas-tools.js&#34;,&#34;getTimezoneOffset&#34;:null,&#34;timezoneOffset&#34;:0,&#34;useUTC&#34;:true},&#34;lang&#34;:{&#34;contextButtonTitle&#34;:&#34;Chart context menu&#34;,&#34;decimalPoint&#34;:&#34;.&#34;,&#34;downloadJPEG&#34;:&#34;Download JPEG image&#34;,&#34;downloadPDF&#34;:&#34;Download PDF document&#34;,&#34;downloadPNG&#34;:&#34;Download PNG image&#34;,&#34;downloadSVG&#34;:&#34;Download SVG vector image&#34;,&#34;drillUpText&#34;:&#34;Back to {series.name}&#34;,&#34;invalidDate&#34;:null,&#34;loading&#34;:&#34;Loading...&#34;,&#34;months&#34;:[&#34;January&#34;,&#34;February&#34;,&#34;March&#34;,&#34;April&#34;,&#34;May&#34;,&#34;June&#34;,&#34;July&#34;,&#34;August&#34;,&#34;September&#34;,&#34;October&#34;,&#34;November&#34;,&#34;December&#34;],&#34;noData&#34;:&#34;No data to display&#34;,&#34;numericSymbols&#34;:[&#34;k&#34;,&#34;M&#34;,&#34;G&#34;,&#34;T&#34;,&#34;P&#34;,&#34;E&#34;],&#34;printChart&#34;:&#34;Print chart&#34;,&#34;resetZoom&#34;:&#34;Reset zoom&#34;,&#34;resetZoomTitle&#34;:&#34;Reset zoom level 1:1&#34;,&#34;shortMonths&#34;:[&#34;Jan&#34;,&#34;Feb&#34;,&#34;Mar&#34;,&#34;Apr&#34;,&#34;May&#34;,&#34;Jun&#34;,&#34;Jul&#34;,&#34;Aug&#34;,&#34;Sep&#34;,&#34;Oct&#34;,&#34;Nov&#34;,&#34;Dec&#34;],&#34;thousandsSep&#34;:&#34; &#34;,&#34;weekdays&#34;:[&#34;Sunday&#34;,&#34;Monday&#34;,&#34;Tuesday&#34;,&#34;Wednesday&#34;,&#34;Thursday&#34;,&#34;Friday&#34;,&#34;Saturday&#34;]}},&#34;type&#34;:&#34;chart&#34;,&#34;fonts&#34;:[],&#34;debug&#34;:false},&#34;evals&#34;:[],&#34;jsHooks&#34;:[]}&lt;/script&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;To conclude, should you need to perform an operation on a &lt;code&gt;data.frame&lt;/code&gt; in R, you can &lt;code&gt;split()&lt;/code&gt; your data into lists of &lt;code&gt;data.frame&lt;/code&gt;s of the required groups, &lt;code&gt;lapply()&lt;/code&gt; a function to each &lt;code&gt;data.frame&lt;/code&gt; in the list; and finally &lt;code&gt;rbind()&lt;/code&gt; those &lt;code&gt;data.frame&lt;/code&gt;s back into a single &lt;code&gt;data.frame&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Are you aware of any other base R solutions to this problem? If so, let me know in the comments!&lt;/p&gt;
&lt;p&gt;In my next &lt;a href=&#34;https://nathaneastwood.github.io/2019/08/20/selecting-the-max-value-in-each-group-data-table/&#34;&gt;blog entry&lt;/a&gt;, we will be looking at how to perform this task using the &lt;code&gt;data.table&lt;/code&gt; package.&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Including Optional Functionality from Other Packages in Your Code</title>
      <link>/2019/09/05/including-optional-functionality-from-other-packages-in-your-code/</link>
      <pubDate>Thu, 05 Sep 2019 21:13:14 -0500</pubDate>
      
      <guid>/2019/09/05/including-optional-functionality-from-other-packages-in-your-code/</guid>
      <description>


&lt;div id=&#34;introduction&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Let’s say you want to write a function with optional functionality which is dependent on the installation of a package that your colleague may not have installed. For example, let’s say you want to have an option to return a &lt;code&gt;data.table&lt;/code&gt; (or a &lt;code&gt;tibble&lt;/code&gt;) instead of a &lt;code&gt;data.frame&lt;/code&gt;, but in this case you don’t want to force your function’s user to have to install &lt;code&gt;data.table&lt;/code&gt; (or &lt;code&gt;tibble&lt;/code&gt; - and its dependencies) just to use your function. Maybe they can’t install it because they are restricted to do so by their IT department or maybe they are working offline. Is it possible to do this?&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;a-toy-example&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;A Toy Example&lt;/h1&gt;
&lt;p&gt;Let’s say we have a simple function which takes a &lt;code&gt;data.frame&lt;/code&gt; and adds a new column which is a multiplication of an existing column, before returning the whole &lt;code&gt;data.frame&lt;/code&gt; with that new column.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;toy_function &amp;lt;- function(data, column, multiple = 2L, as_data_table = FALSE) {
  stopifnot(is.integer(multiple) || is.numeric(multiple))
  new_column_name &amp;lt;- paste(column, multiple, sep = &amp;quot;_&amp;quot;)
  data[, new_column_name] &amp;lt;- data[, column] * multiple
  if (as_data_table) data &amp;lt;- data.table::setDT(data)
  return(data)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Running this function with &lt;code&gt;as_data_table = TRUE&lt;/code&gt; without &lt;code&gt;data.table&lt;/code&gt; installed will give the following error:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;toy_function(mtcars, &amp;quot;mpg&amp;quot;, as_data_table = TRUE)
# Error in loadNamespace(name) : there is no package called ‘data.table’&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is a frustration for the user. This also means that the whole function no longer works and doesn’t return anything. So what can we do? Well, this is where the function &lt;code&gt;requireNamespace()&lt;/code&gt; comes in handy.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;requireNamespace&lt;/code&gt; is a wrapper for &lt;code&gt;loadNamespace&lt;/code&gt; analogous to require that returns a &lt;code&gt;logical&lt;/code&gt; value.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Using &lt;code&gt;requireNamespace()&lt;/code&gt;, we can test whether or not the &lt;code&gt;data.table&lt;/code&gt; package can be loaded from the user’s library before running certain functionality. Let’s take a look at how this changes our function:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;toy_function &amp;lt;- function(data, column, multiple = 2L, as_data_table = FALSE) {
  stopifnot(is.integer(multiple) || is.numeric(multiple))
  new_column_name &amp;lt;- paste(column, multiple, sep = &amp;quot;_&amp;quot;)
  data[, new_column_name] &amp;lt;- data[, column] * multiple
  if (as_data_table) {
    if (!requireNamespace(&amp;quot;data.table&amp;quot;, quietly = TRUE)) {
      warning(&amp;quot;Please install package &amp;#39;data.table&amp;#39; when using &amp;#39;as_data_table = TRUE&amp;#39;&amp;quot;)
      return(data)
    }
    data &amp;lt;- data.table::setDT(data)
  }
  return(data)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now when we run our function, the function will check for a &lt;code&gt;data.table&lt;/code&gt; installation and if it is not available, it will warn us that we need to install &lt;code&gt;data.table&lt;/code&gt; in order to use this functionality; yet it will still return the manipulated data, just as a &lt;code&gt;data.frame&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;toy_function(mtcars, &amp;quot;mpg&amp;quot;, as_data_table = TRUE)
#                      mpg cyl  disp  hp drat    wt  qsec vs am gear carb mpg_2
# Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4  42.0
# Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4  42.0
# Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1  45.6
# ...
# Ferrari Dino        19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6  39.4
# Maserati Bora       15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8  30.0
# Volvo 142E          21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2  42.8
# Warning message:
# In toy_function(mtcars, &amp;quot;mpg&amp;quot;, as_data_table = TRUE) :
#   Please install package &amp;#39;data.table&amp;#39; when using &amp;#39;as_data_table = TRUE&amp;#39;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A real example of this can be seen in the &lt;a href=&#34;https://github.com/fstpackage/fst&#34;&gt;&lt;code&gt;fst&lt;/code&gt;&lt;/a&gt; package. When using the &lt;code&gt;fst::read_fst()&lt;/code&gt; function, the user has the option to return their loaded data &lt;a href=&#34;https://github.com/fstpackage/fst/blob/develop/R/fst.R#L172&#34;&gt;as a &lt;code&gt;data.table&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I really like how this way of using optional functionality does not force additional package downloads on people and also means that your code remains usable on restricted servers or offline. It’s also a great way to not clog up people’s libraries (I’m looking at you &lt;code&gt;tidyverse&lt;/code&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;package-development&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Package Development&lt;/h1&gt;
&lt;p&gt;This solution extends further when developing an R package. My current team is due to start utilising Spark, though our Spark cluster is not yet configured. I have therefore been testing new functionality using a local Spark cluster on our dev environment. Our production environment does not have the &lt;code&gt;sparklyr&lt;/code&gt; package installed yet and so I cannot include any &lt;code&gt;sparklyr&lt;/code&gt; code within my codebase…or can I?&lt;/p&gt;
&lt;p&gt;Typically when your package relies on another package for functionality, you list that package as an &lt;code&gt;Import&lt;/code&gt; within your package’s &lt;code&gt;DESCRIPTION&lt;/code&gt; file. But what this typically means is that when someone installs your package, they will also need to install the &lt;code&gt;Import&lt;/code&gt;s. However if the dependency is not available to install, you will receive the following error upon installation.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;==&amp;gt; R CMD INSTALL --no-multiarch --with-keep.source mypackage

* installing to library ‘/Library/Frameworks/R.framework/Versions/3.5/Resources/library’
ERROR: dependency ‘sparklyr’ is not available for package ‘mypackage’
* removing ‘/Library/Frameworks/R.framework/Versions/3.5/Resources/library/mypackage’

Exited with status 1.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I am forgoing the idea that it probably isn’t best practice to include non-production code which will not work in your package, this blog post is for the purposes of demonstration only; the following is what you &lt;em&gt;could&lt;/em&gt; do.&lt;/p&gt;
&lt;p&gt;Removing &lt;code&gt;sparklyr&lt;/code&gt; from the &lt;code&gt;Import&lt;/code&gt; list would allow us to install the package but we would then face two new issues. Firstly, end users could potentially run the function (even if it isn’t exported) and be faced with that same unhelpful error message we saw earlier.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;my_function()
# Error in loadNamespace(name) : there is no package called ‘sparklyr’&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Secondly, from a developer’s point of view, the &lt;code&gt;R CMD check&lt;/code&gt; would fail - which would in turn fail any CI/CD pipelines.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;devtools::check()
# ...
# ❯ checking dependencies in R code ... WARNING
#   &amp;#39;::&amp;#39; or &amp;#39;:::&amp;#39; import not declared from: ‘sparklyr’&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So within my function, I simply place the below code (or similar) and if the user tries to run the function, it will simply stop and tell them they need to install the &lt;code&gt;sparklyr&lt;/code&gt; package.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;if (!requireNamespace(&amp;quot;sparklyr&amp;quot;, quietly = TRUE)) {
  stop(&amp;quot;Package sparklyr needed.&amp;quot;)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will subsequently pass the &lt;code&gt;R CMD check&lt;/code&gt;. Were this an open source package, I could add &lt;code&gt;sparklyr&lt;/code&gt; to the &lt;code&gt;Suggests&lt;/code&gt; field of the &lt;code&gt;DESCRIPTION&lt;/code&gt; file such that users could install the &lt;code&gt;sparklyr&lt;/code&gt; package to get the additional functionality if they wanted it (this is exactly what the &lt;code&gt;fst&lt;/code&gt; package does).&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;So to conclude if you want to include functionality in your code which relies on other packages but are worried about people not having access to those packages, or simply don’t want to force your users to have to install the additional packages, then consider &lt;code&gt;requireNamespace()&lt;/code&gt;. This is a great way of offering additional functionality without the need to clog up user’s libraries.&lt;/p&gt;
&lt;p&gt;Credit goes to my colleague &lt;a href=&#34;https://twitter.com/jozefhajnala&#34;&gt;Jozef Hajnala&lt;/a&gt; who pointed out this really neat trick!&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>No Visible Binding for Global Variable</title>
      <link>/2019/08/18/no-visible-binding-for-global-variable/</link>
      <pubDate>Sun, 18 Aug 2019 21:13:14 -0500</pubDate>
      
      <guid>/2019/08/18/no-visible-binding-for-global-variable/</guid>
      <description>


&lt;p&gt;Recently I have been working on a very large legacy project which utilises the excellent &lt;a href=&#34;https://github.com/Rdatatable/data.table&#34;&gt;&lt;code&gt;data.table&lt;/code&gt;&lt;/a&gt; package throughout. What this has resulted in is an &lt;code&gt;R CMD check&lt;/code&gt; containing literally thousands of &lt;code&gt;NOTE&lt;/code&gt;s similar to the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;❯ checking R code for possible problems ... NOTE
  my_fn: no visible binding for global variable ‘mpg’&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There are several reasons why you might see these &lt;code&gt;NOTE&lt;/code&gt;s and, for our code base, some of the &lt;code&gt;NOTE&lt;/code&gt;s were potentially more damaging than others. This was a problem as these &lt;code&gt;NOTE&lt;/code&gt;s were hidden firstly by a suppression of them due to a manipulation of the &lt;code&gt;_R_CHECK_CODETOOLS_PROFILE_&lt;/code&gt; option of the &lt;code&gt;.Renviron&lt;/code&gt; file. Once this was removed we discovered the more damaging &lt;code&gt;NOTE&lt;/code&gt;s were hidden within the sheer amount of &lt;code&gt;NOTE&lt;/code&gt;s we had in the &lt;code&gt;R CMD check&lt;/code&gt;.&lt;/p&gt;
&lt;div id=&#34;non-standard-evaluation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Non-standard Evaluation&lt;/h2&gt;
&lt;p&gt;If we have a function where we are using &lt;code&gt;data.table&lt;/code&gt;’s modification by reference features, i.e. we are using a variable in an unquoted fashion (also known as non-standard evaluation (NSE)) then this issue will occur. Take the following function as an example.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;my_fn &amp;lt;- function() {
  mtcars &amp;lt;- data.table::data.table(mtcars)
  mtcars[, mpg_div_hp := mpg / hp]
  mtcars[]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, we would find the following &lt;code&gt;NOTE&lt;/code&gt;s:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;❯ checking R code for possible problems ... NOTE
  my_fn: no visible binding for global variable ‘mpg_div_hp’
  my_fn: no visible binding for global variable ‘mpg’
  my_fn: no visible binding for global variable ‘hp’
  Undefined global functions or variables:
    hp mpg mpg_div_hp&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sometimes you may also see these &lt;code&gt;NOTE&lt;/code&gt;s for syntactic sugar such as &lt;code&gt;!!&lt;/code&gt; or &lt;code&gt;:=&lt;/code&gt; if you haven’t correctly imported the package they come from.&lt;/p&gt;
&lt;p&gt;This is a &lt;a href=&#34;https://github.com/Rdatatable/data.table/issues/850&#34;&gt;well discussed&lt;/a&gt; issue on the internet which only became an issue after a change introduced to the core R code in version 2.15.1. There are two solutions to this problem.&lt;/p&gt;
&lt;div id=&#34;option-one&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Option One&lt;/h3&gt;
&lt;p&gt;Include all variable names within a &lt;code&gt;globalVariables()&lt;/code&gt; call in the package documentation file.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;globalVariables(c(&amp;quot;mpg&amp;quot;, &amp;quot;hp&amp;quot;, &amp;quot;mpg_div_hp&amp;quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For our package, as there are literally thousands of variables to list in this file, it makes it very difficult to maintain this list and makes the file very long. If, however, the variables belong to data which are stored within your package then this can be greatly simplified to&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;globalVariables(names(my_data))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You may wish to import any syntactic sugar functionality here as well. For example&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;globalVariables(c(&amp;quot;:=&amp;quot;, &amp;quot;!!&amp;quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;option-two&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Option Two&lt;/h3&gt;
&lt;p&gt;The second option involves binding the variable locally to the function. At the top of your function you can define the variable as a &lt;code&gt;NULL&lt;/code&gt; value.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;my_fn &amp;lt;- function() {
  mpg &amp;lt;- hp &amp;lt;- mpg_div_hp &amp;lt;- NULL
  mtcars &amp;lt;- data.table::data.table(mtcars)
  mtcars[, mpg_div_hp := mpg / hp]
  mtcars[]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Therefore your variable(s) are now bound to object(s) and so the &lt;code&gt;R CMD check&lt;/code&gt; has nothing to complain about. This is the method that the &lt;code&gt;data.table&lt;/code&gt; team &lt;a href=&#34;https://cran.r-project.org/web/packages/data.table/vignettes/datatable-importing.html&#34;&gt;recommend&lt;/a&gt; and to me, feels like a much neater and more importantly maintainable solution than the first option.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;a-note-on-the-tidyverse&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;A Note on the Tidyverse&lt;/h3&gt;
&lt;p&gt;You may also come across this problem whilst programming using the &lt;code&gt;tidyverse&lt;/code&gt; for which there is a very neat solution. You simply need to be more explicit within your function by using the &lt;a href=&#34;https://cran.r-project.org/web/packages/dplyr/vignettes/programming.html&#34;&gt;&lt;code&gt;.data&lt;/code&gt; pronoun&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#&amp;#39; @importFrom rlang .data
my_fn &amp;lt;- function() {
  mtcars %&amp;gt;% 
    mutate(mpg_div_hp = .data$mpg / .data$hp)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note the import!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;selecting-variables-with-the-data.table-..-prefix&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Selecting Variables with the &lt;code&gt;data.table&lt;/code&gt; &lt;code&gt;..&lt;/code&gt; Prefix&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;NOTE&lt;/code&gt;s can occur when we are using the &lt;code&gt;..&lt;/code&gt; syntax of &lt;code&gt;data.table&lt;/code&gt;, for example&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;double_dot &amp;lt;- function() {
  mtcars &amp;lt;- data.table::data.table(mtcars)
  select_cols &amp;lt;- c(&amp;quot;cyl&amp;quot;, &amp;quot;wt&amp;quot;)
  mtcars[, ..select_cols]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will yield&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;❯ checking R code for possible problems ... NOTE
  Undefined global functions or variables:
    ..select_cols&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this instance, this can be solved by avoiding the &lt;code&gt;..&lt;/code&gt; syntax and using the alternative &lt;code&gt;with = FALSE&lt;/code&gt; notation.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;double_dot &amp;lt;- function() {
  mtcars &amp;lt;- data.table::data.table(mtcars)
  select_cols &amp;lt;- c(&amp;quot;cyl&amp;quot;, &amp;quot;wt&amp;quot;)
  mtcars[, select_cols, with = FALSE]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Even though the &lt;code&gt;..&lt;/code&gt; prefix is syntactic sugar, we cannot use &lt;code&gt;globalVariables(c(&#34;..&#34;))&lt;/code&gt; since the actual variable in this case is &lt;code&gt;..select_cols&lt;/code&gt;; we would therefore need to use &lt;code&gt;globalVariables(c(&#34;..select_cols&#34;))&lt;/code&gt; if we wanted to use the &lt;code&gt;globalVariables()&lt;/code&gt; approach.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;missing-imports&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Missing Imports&lt;/h2&gt;
&lt;p&gt;In our code base, I also found &lt;code&gt;NOTE&lt;/code&gt;s for functions or datasets which were not correctly imported. For example, consider the following simple function.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;Rversion &amp;lt;- function() {
  info &amp;lt;- sessionInfo()
  info$R.version
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This gives the following &lt;code&gt;NOTE&lt;/code&gt;s:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;❯ checking R code for possible problems ... NOTE
  Rversion: no visible global function definition for ‘sessionInfo’
  Consider adding
    importFrom(&amp;quot;utils&amp;quot;, &amp;quot;sessionInfo&amp;quot;)
  to your NAMESPACE file.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here the &lt;code&gt;R CMD check&lt;/code&gt; is rather helpful and tells us the solution; we need to ensure that we explicitly import the function from the &lt;code&gt;utils&lt;/code&gt; package in the documentation. This can easily be done with the &lt;a href=&#34;https://github.com/r-lib/roxygen2&#34;&gt;&lt;code&gt;roxygen2&lt;/code&gt;&lt;/a&gt; package by including an &lt;code&gt;@importFrom utils sessionInfo&lt;/code&gt; tag.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;trying-to-call-removed-functionality&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Trying to Call Removed Functionality&lt;/h2&gt;
&lt;p&gt;If you have a function which has been removed from your package but attempt to call it from another function, R will only give you a &lt;code&gt;NOTE&lt;/code&gt; about this.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;use_non_existent_function &amp;lt;- function() {
  this_function_doesnt_exist()
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will give the &lt;code&gt;NOTE&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;❯ checking R code for possible problems ... NOTE
  use_non_existent_function: no visible global function definition for
    ‘this_function_doesnt_exist’&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Of course it goes without saying that you should make sure to remove any calls to functions which have been removed from your package. As a side note, when I first started working on the project, I was initially unaware that within our package we had the option &lt;code&gt;_R_CHECK_CODETOOLS_PROFILE_ = &#34;suppressUndefined = TRUE&#34;&lt;/code&gt; set within our &lt;code&gt;.Renviron&lt;/code&gt; file which will suppresses all unbound global variable &lt;code&gt;NOTE&lt;/code&gt;s from appearing in the &lt;code&gt;R CMD check&lt;/code&gt;. However given that this can mask these deeper issues within your package, such as not recognising when a function calls functionality which has been removed from the package. This can end up meaning the end user can face nasty and confusing error messages. Therefore I would not recommend using this setting and would suggest tackling each of your packages &lt;code&gt;NOTE&lt;/code&gt;s individually to remove them all.&lt;/p&gt;
&lt;p&gt;I actually discovered all of our package &lt;code&gt;NOTE&lt;/code&gt;s when introducing the &lt;a href=&#34;https://github.com/jimhester/lintr&#34;&gt;&lt;code&gt;lintr&lt;/code&gt;&lt;/a&gt; package to our CI pipeline. &lt;code&gt;lintr&lt;/code&gt; will pick up on some – but not all – of these unbound global variable problems (&lt;code&gt;&#39;lintr&lt;/code&gt; of course does not take the &lt;code&gt;_R_CHECK_CODETOOLS_PROFILE_&lt;/code&gt; into account). Take our original function as an example&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;my_fn &amp;lt;- function() {
  mtcars &amp;lt;- data.table::data.table(mtcars)
  mtcars[, mpg_div_hp := mpg / hp]
  mtcars[]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, &lt;code&gt;lintr&lt;/code&gt; will highlight the variables &lt;code&gt;mpg&lt;/code&gt; and &lt;code&gt;hp&lt;/code&gt; as problems but it currently won’t highlight the variables on the LHS of &lt;code&gt;:=&lt;/code&gt;, i.e. &lt;code&gt;mpg_div_hp&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;When developing your package, if you are experiencing these unbound global variables &lt;code&gt;NOTE&lt;/code&gt;s you should&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Strive to define any unbound variables locally within a function.&lt;/li&gt;
&lt;li&gt;Ensure that any functions or data from external packages (including &lt;code&gt;utils&lt;/code&gt;, &lt;code&gt;stats&lt;/code&gt;, etc.) have the correct &lt;code&gt;@importFrom&lt;/code&gt; tag&lt;/li&gt;
&lt;li&gt;Do not suppress this check in the &lt;code&gt;.Renviron&lt;/code&gt; file and the solutions proposed here should remove the current need to do so&lt;/li&gt;
&lt;li&gt;Any package wide unbound variables, which are typically syntactic sugar (e.g. &lt;code&gt;:=&lt;/code&gt;), should be defined within the package description file inside a &lt;code&gt;globalVariables()&lt;/code&gt; function, which should be a very short and maintainable list.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Extending sparklyr: Data Types</title>
      <link>/2018/03/08/extending-sparklyr-data-types/</link>
      <pubDate>Thu, 08 Mar 2018 21:13:14 -0500</pubDate>
      
      <guid>/2018/03/08/extending-sparklyr-data-types/</guid>
      <description>


&lt;div id=&#34;tldr&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;TL;DR&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;sparklyr&lt;/code&gt; maps R data types and data storage types to Scala, but it doesn’t handle all data storage types. This blog post discusses how to generate Scala data storage types from the R side, that are not generated by &lt;code&gt;sparklyr&lt;/code&gt;. You can do this by using the &lt;code&gt;sparklyr::invoke_new&lt;/code&gt; function to generate the objects you want in Java or Scala, for example a &lt;code&gt;java.util.ArrayList&lt;/code&gt;, and then &lt;code&gt;sparklyr::invoke&lt;/code&gt; methods of the class to add data to it, or convert it to the type you need. Read on to see how to deal with different data storage types from the Scala side or skip ahead to see how to &lt;a href=&#34;#generating-scala-data-types-from-r&#34;&gt;generate Scala data storage types from R&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;introduction&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;When working to &lt;a href=&#34;http://spark.rstudio.com/extensions/&#34;&gt;extend&lt;/a&gt; the &lt;code&gt;sparklyr&lt;/code&gt; package, for example to call custom Scala libraries, oftentimes you will come across Scala methods which require you to use different data storage types to those automatically handled by &lt;code&gt;sparklyr&lt;/code&gt;. When using the &lt;code&gt;invoke&lt;/code&gt; family of functions, R data types map to Scala data types, but &lt;code&gt;sparklyr&lt;/code&gt; &lt;a href=&#34;https://github.com/rstudio/sparklyr/issues/1324&#34;&gt;currently&lt;/a&gt; only handles certain R data storage type mappings. The below table shows the data mappings currently handled by &lt;code&gt;sparklyr&lt;/code&gt;:&lt;/p&gt;
&lt;table style=&#34;width:100%&#34;&gt;
&lt;tr&gt;
&lt;th&gt;
R Type
&lt;/th&gt;
&lt;th&gt;
Scala Type
&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
logical
&lt;/td&gt;
&lt;td&gt;
Boolean
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
numeric
&lt;/td&gt;
&lt;td&gt;
Double
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
integer
&lt;/td&gt;
&lt;td&gt;
Integer
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
character
&lt;/td&gt;
&lt;td&gt;
String
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
list
&lt;/td&gt;
&lt;td&gt;
Array
&lt;/td&gt;
&lt;/tr&gt;
&lt;caption&gt;
Table 1: R to Scala type mappings available in &lt;code&gt;sparklyr&lt;/code&gt;
&lt;/caption&gt;
&lt;/table&gt;
&lt;p&gt;So Scala functions with parameters that require a &lt;code&gt;List&lt;/code&gt; or a &lt;code&gt;Seq&lt;/code&gt;, for example, need to be handled in a different way. There are two ways we can approach this problem; from the Scala side and from the R side. We will explore both approaches.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;other-scala-data-types&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Other Scala Data Types&lt;/h1&gt;
&lt;div id=&#34;solutions-from-the-scala-side&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solutions from the Scala Side&lt;/h2&gt;
&lt;p&gt;There are several ways that this issue can be overcome from the Scala side, here we highlight three: &lt;a href=&#34;#using-different-data-types-in-scala&#34;&gt;changing the data type&lt;/a&gt; used within Scala; using &lt;a href=&#34;#using-overloading&#34;&gt;overloading&lt;/a&gt;; and defining a &lt;a href=&#34;#defining-a-new-scala-class&#34;&gt;specific R class&lt;/a&gt; to be called from R. These are discussed in detail below.&lt;/p&gt;
&lt;div id=&#34;using-different-data-types-in-scala&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Using Different Data Types in Scala&lt;/h3&gt;
&lt;p&gt;One obvous way we could fix this problem is to rewrite the Scala code to use a different parameter type in the Scala method. For example, we could use an &lt;code&gt;Array&lt;/code&gt; which would require us passing a &lt;code&gt;list()&lt;/code&gt; on the R side. However, this is not ideal if your project is large, has lots of legacy code and uses other APIs such as &lt;code&gt;PySpark&lt;/code&gt;; you may end up changing a lot of code.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;using-overloading&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Using Overloading&lt;/h3&gt;
&lt;p&gt;We can instead use &lt;a href=&#34;https://www.javatpoint.com/scala-method-overloading&#34;&gt;overloading&lt;/a&gt;, which allows us to define methods of same name, in the same class, but having either different parameters or data types, though this &lt;a href=&#34;https://stackoverflow.com/questions/2510108/why-avoid-method-overloading&#34;&gt;has many issues&lt;/a&gt;. We would also need to write additional tests for the additional methods. You can think of this as working like R’s S3 methods - for S3 methods the method behaviour will change based on the object’s class.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;defining-a-new-scala-class&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Defining A New Scala Class&lt;/h3&gt;
&lt;p&gt;To avoid the possible issues of overloading, we can define two separate classes, &lt;code&gt;myClass&lt;/code&gt; and &lt;code&gt;myClassR&lt;/code&gt;. These will both call upon the same underlying &lt;a href=&#34;https://docs.scala-lang.org/overviews/core/implicit-classes.html&#34;&gt;implicit&lt;/a&gt; class which does the bulk of the work for the method. The difference is the data types that are passed into &lt;code&gt;myClass&lt;/code&gt; and &lt;code&gt;myClassR&lt;/code&gt;. &lt;code&gt;myClass&lt;/code&gt; will take the data type you want to use, whereas &lt;code&gt;myClassR&lt;/code&gt; will take the data type passed to it by &lt;code&gt;sparklyr&lt;/code&gt; and then convert it before calling the implicit. Of course using this approach effectively doubles our code and is therefore very wasteful; we would also again, need to write additional tests for this new class.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;solutions-from-the-r-side&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solutions from the R Side&lt;/h2&gt;
&lt;div id=&#34;generating-scala-data-storage-types-from-r&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Generating Scala Data Storage Types from R&lt;/h3&gt;
&lt;p&gt;We can actually forgo any changes on the Scala side of our code by generating what we need on the R side. Imagine we wanted to generate a Scala &lt;code&gt;Seq&lt;/code&gt; as an example, first we create a Java &lt;code&gt;ArrayList&lt;/code&gt; in the Spark environment and incrementally &lt;code&gt;add&lt;/code&gt; data to it using the following code:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(sparklyr)
sc &amp;lt;- spark_connect(master = &amp;quot;local&amp;quot;)
# map some R vector `x` to a java ArrayList
x &amp;lt;- c(1, 2, 3)
al &amp;lt;- invoke_new(sc, &amp;quot;java.util.ArrayList&amp;quot;)
lapply(x, FUN = function(y){invoke(al, &amp;quot;add&amp;quot;, y)})&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note we don’t need to reassign the results of the &lt;code&gt;lapply&lt;/code&gt; because it is adding values to the Scala &lt;code&gt;List&lt;/code&gt; in the JVM. Then using the &lt;a href=&#34;https://www.scala-lang.org/api/2.12.3/scala/collection/JavaConversions$.html&#34;&gt;&lt;code&gt;JavaConversions&lt;/code&gt; Scala package&lt;/a&gt;, we convert the &lt;code&gt;Array&lt;/code&gt; to a &lt;code&gt;Seq&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;invoke_static(sc, &amp;quot;scala.collection.JavaConversions&amp;quot;, &amp;quot;asScalaBuffer&amp;quot;, al) %&amp;gt;%
  invoke(&amp;quot;toSeq&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Putting this all together in a function gives&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;scala_seq &amp;lt;- function(sc, x) {
  al &amp;lt;- invoke_new(sc, &amp;quot;java.util.ArrayList&amp;quot;)
  lapply(
    x,
    FUN = function(y) {
      invoke(al, &amp;quot;add&amp;quot;, y)
    }
  )
  invoke_static(sc, &amp;quot;scala.collection.JavaConversions&amp;quot;, &amp;quot;asScalaBuffer&amp;quot;, al) %&amp;gt;%
    invoke(&amp;quot;toSeq&amp;quot;)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Calling this function returns a reference to the Scala object (&lt;code&gt;spark_jobj&lt;/code&gt;).&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# connect to spark
sc &amp;lt;- sparklyr::spark_connect(master = &amp;quot;local&amp;quot;)

# create a scala seq object
scala_seq(sc, c(1, 2, 3))
# &amp;lt;jobj[16]&amp;gt;
#   scala.collection.convert.Wrappers$JListWrapper
#   Buffer(1.0, 2.0, 3.0)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You will note that the output we have received tells us we have created a &lt;code&gt;Buffer&lt;/code&gt; but &lt;code&gt;Buffer&lt;/code&gt; (and &lt;code&gt;List&lt;/code&gt;) both &lt;a href=&#34;https://stackoverflow.com/questions/11126577/why-are-buffer-and-list-objects-equal-even-they-are-from-different-classes&#34;&gt;belong to the same category (sequence)&lt;/a&gt;. If what we needed was actually a &lt;code&gt;List&lt;/code&gt; object, then we simply have to &lt;code&gt;invoke&lt;/code&gt; the &lt;code&gt;toList&lt;/code&gt; method on a &lt;code&gt;Seq&lt;/code&gt; (or &lt;code&gt;Buffer&lt;/code&gt;) object. The below function shows this in action, again this returns a reference to the Scala object (&lt;code&gt;spark_jobj&lt;/code&gt;) to the R console.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;scala_list &amp;lt;- function(sc, x) {
  scala_seq(sc, x) %&amp;gt;%
    invoke(&amp;quot;toList&amp;quot;)
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# create a scala list
scala_list(sc, c(1, 2, 3))
# &amp;lt;jobj[21]&amp;gt;
#   scala.collection.immutable.$colon$colon
#   List(1.0, 2.0, 3.0)

# disconnect the spark connection
spark_disconnect(sc = sc)
# NULL&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Similar results can be achieved for other data types. These new data storage types can now be used in Scala function calls when extending &lt;code&gt;sparklyr&lt;/code&gt;, we simply generate the data in the JVM and pass the reference to the function we &lt;code&gt;invoke&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Project Euler in R</title>
      <link>/2018/02/28/project-euler-in-r/</link>
      <pubDate>Wed, 28 Feb 2018 21:13:14 -0500</pubDate>
      
      <guid>/2018/02/28/project-euler-in-r/</guid>
      <description>


&lt;div id=&#34;project-euler&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Project Euler&lt;/h1&gt;
&lt;p&gt;This is just a short blog post to raise some awareness to some fun programming and mathematical challenges I recently came across, hosted on &lt;a href=&#34;https://projecteuler.net&#34;&gt;Project Euler&lt;/a&gt;. The idea behind Project Euler is to provide abstract programming challenges for people to develop their skills and learn new concepts in a recreational way. The problems range in difficulty and are aimed at:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;students for whom the basic curriculum is not feeding their hunger to learn, adults whose background was not primarily mathematics but had an interest in things mathematical, and professionals who want to keep their problem solving and mathematics on the cutting edge.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/topics/project-euler&#34;&gt;Many, many attempts&lt;/a&gt; have been made to solve these problems in different languages and in fact the &lt;a href=&#34;http://www.rosettacode.org/wiki/Category:Programming_Tasks&#34;&gt;Rosetta Code&lt;/a&gt; website hosts solutions to lots of these challenges. However in my (admittedly brief) search I couldn’t find any one place with hosted R solutions. Thus, I decided to have a go at a few of them, package them up and host them on &lt;a href=&#34;https://github.com/nathaneastwood/euler&#34;&gt;GitHub&lt;/a&gt; with a view to collecting solutions for all of the challenges. With a current list of 611 Project Euler challenges, however, it will take me quite a while to get through them all and so I have enlisted the help of some of my colleagues from Mango Solutions (&lt;a href=&#34;https://github.com/thisisnic&#34;&gt;thisisnic&lt;/a&gt; and &lt;a href=&#34;https://github.com/adfi&#34;&gt;adfi&lt;/a&gt;) who have submitted some solutions. Even so, this is a lot of problems for so few people and so I ask you, my readers, to feel free to submit pull requests via GitHub for any potential solutions you may come up with.&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Accessing Private Methods from an R6 Class</title>
      <link>/2017/08/13/accessing-private-methods-from-an-r6-class/</link>
      <pubDate>Sun, 13 Aug 2017 21:13:14 -0500</pubDate>
      
      <guid>/2017/08/13/accessing-private-methods-from-an-r6-class/</guid>
      <description>


&lt;p&gt;I recently wrote a package to solve the &lt;a href=&#34;http://chrisdone.com/posts/twitter-problem-loeb&#34;&gt;Twitter Waterflow Problem&lt;/a&gt; using an &lt;code&gt;R6&lt;/code&gt; class. You can view the package &lt;a href=&#34;https://github.com/nathaneastwood/waterflow&#34;&gt;here&lt;/a&gt; and read about how I approached the problem &lt;a href=&#34;https://nathaneastwood.github.io/2017/08/09/2017-08-09-twitter-waterflow-problem/&#34;&gt;here&lt;/a&gt;. In this blog post, I want to highlight how you can access &lt;code&gt;private&lt;/code&gt; members of an &lt;code&gt;R6&lt;/code&gt; class which Winston Chang mentioned in his &lt;a href=&#34;https://channel9.msdn.com/Events/useR-international-R-User-conferences/useR-International-R-User-2017-Conference/The-R6-Class-System&#34;&gt;useR!2017 talk&lt;/a&gt;. I will use the &lt;code&gt;waterflow&lt;/code&gt; package for this example. Within the &lt;code&gt;R6&lt;/code&gt; waterflow class there is a &lt;code&gt;private&lt;/code&gt; member function, or method, that converts the data you provide the class with, and the data it calculates, into a tidy &lt;code&gt;data.frame&lt;/code&gt; used for generating a plot. However what if we already have the data that this function needs to be supplied with? How can we just run this function on the fly? If we try to call it directly, we get an error.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(waterflow)
wall &amp;lt;- c(2, 5, 1, 2, 3, 4, 7, 7, 6)
water &amp;lt;- c(2, 5, 1, 2, 3, 4, 7, 7, 6)
p &amp;lt;- waterflow$new(wall)
p$tidyWater(water, wall)
# Error in eval(expr, envir, enclos): attempt to apply non-function&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Instead, what we need to do is extract the method from the class’ environment, &lt;code&gt;.__enclos_env__&lt;/code&gt;, which allows us access to &lt;code&gt;private&lt;/code&gt; members of the class.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;p$.__enclos_env__$private$tidyWater(water, wall)
#    pos  type val
# 1    1 water   2
# 2    2 water   5
# 3    3 water   1
# 4    4 water   2
# 5    5 water   3
# 6    6 water   4
# 7    7 water   7
# 8    8 water   7
# 9    9 water   6
# 10   1  wall   2
# 11   2  wall   5
# 12   3  wall   1
# 13   4  wall   2
# 14   5  wall   3
# 15   6  wall   4
# 16   7  wall   7
# 17   8  wall   7
# 18   9  wall   6&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>The Twitter Waterflow Problem</title>
      <link>/2017/08/09/the-twitter-waterflow-problem/</link>
      <pubDate>Wed, 09 Aug 2017 21:13:14 -0500</pubDate>
      
      <guid>/2017/08/09/the-twitter-waterflow-problem/</guid>
      <description>


&lt;div id=&#34;introduction&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;I was recently introduced to the &lt;a href=&#34;http://chrisdone.com/posts/twitter-problem-loeb&#34;&gt;Twitter Waterflow Problem&lt;/a&gt; and I decided it was interesting enough to try and complete the challenge in R. Consider the following picture:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/post/2017-08-09-twitter-waterflow-problem_files/figure-html/unfilled-1.png&#34; width=&#34;800px&#34; /&gt;&lt;/p&gt;
&lt;p&gt;This plot shows a series of walls and empty valleys. We can represent this picture by an array of integers, where the value at each index is the height of the wall. So in this case, the array of integers can be defined as:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;wall &amp;lt;- c(2, 5, 1, 2, 3, 4, 7, 7, 6)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now imagine it rains. How much water is going to be accumulated in puddles between walls? No puddles are formed at edges of the wall and water is considered to simply run off the edge. We count volume in square blocks of 1×1. Thus, we are left with a puddle between column 2 and column 7 and the volume is 10.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;the-approach&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The Approach&lt;/h2&gt;
&lt;p&gt;The approach I took was one of many ways you could solve this problem. I chose to treat each column (wall) as an index and then for each index I implement a loop:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Find the height of the current index&lt;/li&gt;
&lt;li&gt;Find the maximum height of the walls to the left of the current index&lt;/li&gt;
&lt;li&gt;Find the maximum height of the walls to the right of the index&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I then work out what the smallest maximum height is between the maximum heights to the left and right of the current index. If this smallest height minus the current index height is greater than zero, then I know how many blocks will fill with water for the current index. Of course, if the smallest maximum height to the left or right is less than the current height, then I get the run off. Converting this to code looks like this:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;len &amp;lt;- length(wall)
# pre-allocate memory to make the loop more efficient
water &amp;lt;- rep(0, len)
for (i in seq_along(wall)) {
  currentHeight &amp;lt;- wall[i]
  maxLeftHeight &amp;lt;- if (i &amp;gt; 1) {
    max(wall[1:(i - 1)])
  } else {
    0
  }
  maxRightHeight &amp;lt;- if (i == len) {
    0
  } else {
    max(wall[(i + 1):len])
  }
  smallestMaxHeight &amp;lt;- min(maxLeftHeight, maxRightHeight)
  water[i] &amp;lt;- if (smallestMaxHeight - currentHeight &amp;gt; 0) {
    smallestMaxHeight - currentHeight
  } else {
    0
  }
}
water
# [1] 0 0 4 3 2 1 0 0 0&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This returns a vector of the number of blocks of water at each index.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;the-r6-class&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The R6 Class&lt;/h2&gt;
&lt;p&gt;For this problem I chose to use the &lt;a href=&#34;https://github.com/r-lib/R6&#34;&gt;&lt;code&gt;R6&lt;/code&gt;&lt;/a&gt; class system because it is very self contained. The &lt;code&gt;R6&lt;/code&gt; class system is different from the functional &lt;code&gt;S3&lt;/code&gt; and &lt;code&gt;S4&lt;/code&gt; class systems found in base R in that it is an encapsulated class system. Some key differences between the two are:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Functional:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Objects contain data&lt;/li&gt;
&lt;li&gt;Class methods are separate from objects&lt;/li&gt;
&lt;li&gt;Objects are immutable - they cannot be changed after they have been created&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Encapsulated:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Objects contain methods and data&lt;/li&gt;
&lt;li&gt;Objects are mutable&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Winston Chang details these differences very well in his &lt;a href=&#34;https://channel9.msdn.com/Events/useR-international-R-User-conferences/useR-International-R-User-2017-Conference/The-R6-Class-System&#34;&gt;userR!2017 talk&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I wanted the user to be able to acquire two key pieces of information: the total blocks of water and the filled plot. I therefore created three &lt;code&gt;public&lt;/code&gt; methods inside an &lt;code&gt;R6&lt;/code&gt; class and placed the class in a simple package which can be found &lt;a href=&#34;https://github.com/nathaneastwood/waterflow&#34;&gt;here&lt;/a&gt;. &lt;code&gt;public&lt;/code&gt; methods are a list of functions (and/or non-functions) which are essentially methods (or data) of the class that are intended to be used by the user of the class.&lt;/p&gt;
&lt;p&gt;When writing a new &lt;code&gt;R6&lt;/code&gt; class, we often want to perform some initial functionality when we instantiate an object of this class. This is true in our case as when we instantiate a new object of class &lt;code&gt;waterflow&lt;/code&gt;, we want it to calculate the heights of the water straight away. We therefore call our earlier function &lt;code&gt;initialize&lt;/code&gt; and place it inside the &lt;code&gt;public&lt;/code&gt; list.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;initialize = function(wall = NULL) {
  if (is.null(wall)) {
    stop(&amp;quot;Please provide some wall heights&amp;quot;)
  }
  if (!is.numeric(wall)) {
    stop(&amp;quot;Please provide a numeric vector&amp;quot;)
  }
  len &amp;lt;- length(wall)
  water &amp;lt;- rep(0, len)
  for (i in seq_along(wall)) {
    currentHeight &amp;lt;- wall[i]
    maxLeftHeight &amp;lt;- if (i &amp;gt; 1) {
      max(wall[1:(i - 1)])
    } else {
      0
    }
    maxRightHeight &amp;lt;- if (i == len) {
      0
    } else {
      max(wall[(i + 1):len])
    }
    smallestMaxHeight &amp;lt;- min(maxLeftHeight, maxRightHeight)
    water[i] &amp;lt;- if (smallestMaxHeight - currentHeight &amp;gt; 0) {
      smallestMaxHeight - currentHeight
    } else {
      0
    }
  }
  private$heights &amp;lt;- private$tidyWater(water, wall)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note, we have one key difference here, we are assigning the results to members of the &lt;code&gt;private&lt;/code&gt; list within our object. Once we have calculated our &lt;code&gt;water&lt;/code&gt; heights, we use them along with our &lt;code&gt;wall&lt;/code&gt; heights in the function &lt;code&gt;private$tidyWater()&lt;/code&gt; and assign the resulting &lt;code&gt;data.frame&lt;/code&gt; to &lt;code&gt;private$heights&lt;/code&gt;. The &lt;code&gt;private&lt;/code&gt; argument is a list which contains methods (and/or data) which are internal to the class and are not intended to be used by the user. We do similar things when writing packages - we explicitly export the functionality we want other people to use and don’t export functionality that is only used within the package itself.&lt;/p&gt;
&lt;p&gt;So to use the class, first we instantiate the class with some data in a call to &lt;code&gt;$new()&lt;/code&gt; which in turn runs the above &lt;code&gt;initialize&lt;/code&gt; function.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(waterflow)
wall &amp;lt;- c(2, 5, 1, 2, 3, 4, 7, 7, 6)
p &amp;lt;- waterflow$new(wall)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So now we have an object called &lt;code&gt;p&lt;/code&gt; which is of class &lt;code&gt;waterflow&lt;/code&gt; (and &lt;code&gt;R6&lt;/code&gt;). &lt;code&gt;p&lt;/code&gt; contains the data, as well as the (&lt;code&gt;public&lt;/code&gt;) methods we can perform on that data.&lt;/p&gt;
&lt;p&gt;Typically when we return &lt;code&gt;p&lt;/code&gt;, &lt;code&gt;R6&lt;/code&gt; objects have a default &lt;code&gt;print&lt;/code&gt; method that lists all members of the object but here there is a custom &lt;code&gt;$print()&lt;/code&gt; function that returns &lt;code&gt;heights&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;p
#    pos  type val
# 1    1 water   0
# 2    2 water   0
# 3    3 water   4
# 4    4 water   3
# 5    5 water   2
# 6    6 water   1
# 7    7 water   0
# 8    8 water   0
# 9    9 water   0
# 10   1  wall   2
# 11   2  wall   5
# 12   3  wall   1
# 13   4  wall   2
# 14   5  wall   3
# 15   6  wall   4
# 16   7  wall   7
# 17   8  wall   7
# 18   9  wall   6&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can still return the members of the object by looking at the structure of &lt;code&gt;p&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;str(p)
# Classes &amp;#39;waterflow&amp;#39;, &amp;#39;R6&amp;#39; &amp;lt;waterflow&amp;gt;
#   Public:
#     clone: function (deep = FALSE) 
#     initialize: function (wall = NULL) 
#     plot: function () 
#     print: function () 
#     total: function () 
#   Private:
#     heights: data.frame
#     tidyWater: function (water, wall)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To calculate the total water that fills the valleys, we sum over the &lt;code&gt;heights&lt;/code&gt; object for the values of the &lt;code&gt;water&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;total = function() {
  sum(private$heights[private$heights$type %in% &amp;quot;water&amp;quot;, &amp;quot;val&amp;quot;])
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Calling the &lt;code&gt;public&lt;/code&gt; method &lt;code&gt;$total()&lt;/code&gt; gives the expected result.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;p$total()
# [1] 10&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To call the plot, we access the &lt;code&gt;public&lt;/code&gt; method &lt;code&gt;$plot()&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;p$plot()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;/post/2017-08-09-twitter-waterflow-problem_files/figure-html/plotCall-1.png&#34; width=&#34;800px&#34; /&gt;&lt;/p&gt;
&lt;p&gt;The completed class looks like this&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;waterflow &amp;lt;- R6Class(
  &amp;quot;waterflow&amp;quot;,
  public = list(
    initialize = function(wall = NULL) {
      if (is.null(wall)) {
        stop(&amp;quot;Please provide some wall heights&amp;quot;)
      }
      if (!is.numeric(wall)) {
        stop(&amp;quot;Please provide a numeric vector&amp;quot;)
      }
      len &amp;lt;- length(wall)
      water &amp;lt;- rep(0, len)
      for (i in seq_along(wall)) {
        currentHeight &amp;lt;- wall[i]
        maxLeftHeight &amp;lt;- if (i &amp;gt; 1) {
          max(wall[1:(i - 1)])
        } else {
          0
        }
        maxRightHeight &amp;lt;- if (i == len) {
          0
        } else {
          max(wall[(i + 1):len])
        }
        smallestMaxHeight &amp;lt;- min(maxLeftHeight, maxRightHeight)
        water[i] &amp;lt;- if (smallestMaxHeight - currentHeight &amp;gt; 0) {
          smallestMaxHeight - currentHeight
        } else {
          0
        }
      }
      private$heights &amp;lt;- private$tidyWater(water, wall)
    },
    plot = function() {
      ggplot(private$heights) +
        geom_col(
          aes(x = pos + 1 / 2, y = val, fill = type),
          width = 1, show.legend = FALSE
        ) +
        scale_fill_manual(values = c(&amp;quot;dodgerblue2&amp;quot;, &amp;quot;grey50&amp;quot;)) +
        scale_x_continuous(breaks = seq(0, max(private$heights$pos), 1)) +
        theme(
          panel.background = element_blank(),
          panel.ontop = TRUE,
          panel.grid.minor.x = element_blank(),
          panel.grid.minor.y = element_line(colour = &amp;quot;white&amp;quot;, size = 0.5),
          panel.grid.major.x = element_line(colour = &amp;quot;white&amp;quot;, size = 0.5),
          panel.grid.major.y = element_line(colour = &amp;quot;white&amp;quot;, size = 0.5),
          axis.ticks = element_blank(),
          text = element_blank()
        )
    },
    print = function() print(private$heights),
    total = function() {
      sum(private$heights[private$heights$type %in% &amp;quot;water&amp;quot;, &amp;quot;val&amp;quot;])
    }
  ),
  private = list(
    heights = NULL,
    tidyWater = function(water, wall) {
      data.frame(
        pos = seq_along(wall),
        type = factor(
          rep(c(&amp;quot;water&amp;quot;, &amp;quot;wall&amp;quot;), each = length(wall)),
          levels = c(&amp;quot;water&amp;quot;, &amp;quot;wall&amp;quot;)
        ),
        val = c(water, wall)
      )
    }
  )
)&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;disadvantages-of-r6&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Disadvantages of R6&lt;/h3&gt;
&lt;p&gt;Overall &lt;code&gt;R6&lt;/code&gt; is a great package with one or two downsides but these are mostly not too worrying. For one thing, &lt;code&gt;R6&lt;/code&gt; is a separate package that users have to load or use as an import but given that it is such a lightweight package and doesn’t have any imports of its own, it’s nothing to be concerned about. Also, &lt;code&gt;R6&lt;/code&gt; doesn’t have any strict type checking but this is remedied by including your own type checking in your methods. The main bug bear I have with &lt;code&gt;R6&lt;/code&gt; is the lack of support from &lt;a href=&#34;https://github.com/klutometis/roxygen&#34;&gt;&lt;code&gt;Roxygen2&lt;/code&gt;&lt;/a&gt; out of the box and this has been an &lt;a href=&#34;https://github.com/klutometis/roxygen/issues/388&#34;&gt;open issue&lt;/a&gt; for a while.&lt;/p&gt;
&lt;p&gt;Also posted on the &lt;a href=&#34;https://www.mango-solutions.com/blog/the-twitter-waterflow-problem&#34;&gt;Mango Solutions blog&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Automatically Building, Testing and Deploying bookdown with Travis and GitHub Pages</title>
      <link>/2017/05/16/automatically-building-testing-and-deploying-bookdown-with-travis-and-github-pages/</link>
      <pubDate>Tue, 16 May 2017 21:13:14 -0500</pubDate>
      
      <guid>/2017/05/16/automatically-building-testing-and-deploying-bookdown-with-travis-and-github-pages/</guid>
      <description>


&lt;p&gt;I recently began writing some documentation around coding standards using &lt;code&gt;bookdown&lt;/code&gt;. The workflow I was using was to write the new sections of the book, build the book and then push the changes to GitHub where it is &lt;a href=&#34;https://datasciencecampus.github.io/coding-standards/&#34;&gt;hosted&lt;/a&gt; using GitHub Pages. This was clearly one manual step too far for me as I consistently forgot to build the book before I pushed the changes to GitHub meaning those changes were not shown on the subsequent web pages. Then when I finally did manage to convert the &lt;code&gt;Rmarkdown&lt;/code&gt; to &lt;code&gt;html&lt;/code&gt;, I found that some links would be broken or missing, I therefore needed two things:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;I needed a way to automatically build the book.&lt;/li&gt;
&lt;li&gt;I needed a way to test my html files.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I was already familiar with Travis having used it for some of my packages. I therefore decided that a smart way to handle the build would be to build the book on Travis and push the subsequent &lt;code&gt;docs&lt;/code&gt; folder back to my &lt;code&gt;gh-pages&lt;/code&gt; branch on GitHub using Travis’ inbuilt &lt;a href=&#34;https://docs.travis-ci.com/user/deployment/pages/&#34;&gt;deployment method&lt;/a&gt; for deploying to GitHub Pages. But before it pushed these changes, I would be able to test the &lt;code&gt;html&lt;/code&gt; files with the &lt;code&gt;Ruby&lt;/code&gt; library, &lt;a href=&#34;https://github.com/gjtorikian/html-proofer&#34;&gt;&lt;code&gt;html-proofer&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;HTMLProofer is a set of tests to validate your HTML output. These tests check if your image references are legitimate, if they have alt tags, if your internal links are working, and so on. It’s intended to be an all-in-one checker for your output.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We can achieve all of this with the following &lt;code&gt;.travis.yml&lt;/code&gt; file.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;language: R
sudo: required
cache: packages

r_packages:
  - bookdown

before_script:
  - chmod +x ./scripts/cibuild

before_install:                           # Install Ruby and html-proofer
  - rvm get stable --auto-dotfiles
  - rvm install 2.3.3
  - gem install html-proofer

script:
  - ./scripts/cibuild

deploy:
  provider: pages                         # Specify the gh-pages deployment method
  skip_cleanup: true                      # Don&amp;#39;t remove files
  github_token: $GITHUB_TOKEN             # Set in travis-ci.org dashboard
  local_dir: docs                         # Deploy the docs folder
  on:
    branch: master

env:
  global:
    - NOKOGIRI_USE_SYSTEM_LIBRARIES=true  # Speed up the html-proofer

notifications:
  email: false&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note, the &lt;code&gt;GITHUB_TOKEN&lt;/code&gt; is a GitHub Personal Access Token (PAT) that you store in the &lt;a href=&#34;travis-ci.org&#34;&gt;travis-ci.org&lt;/a&gt; dashboard under the settings for the repository.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/img/github_token.png&#34; width=&#34;800px&#34; /&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;cibuild&lt;/code&gt; is then a simple file that first renders the book (&lt;code&gt;_build.sd&lt;/code&gt;), thus creating the &lt;code&gt;html&lt;/code&gt; files within a &lt;code&gt;docs&lt;/code&gt; folder (which is specified in the &lt;code&gt;output_dir:&lt;/code&gt; tag in my &lt;code&gt;_bookdown.yml&lt;/code&gt; file) and then it runs the &lt;code&gt;html-proofer&lt;/code&gt; on the resulting &lt;code&gt;html&lt;/code&gt; files.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;. _build.sh
htmlproofer ./docs&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Where the &lt;code&gt;_build.sh&lt;/code&gt; script is just:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/bin/sh

Rscript -e &amp;quot;bookdown::render_book(&amp;#39;index.Rmd&amp;#39;, &amp;#39;bookdown::gitbook&amp;#39;)&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If all is well, Travis will then push the &lt;code&gt;html&lt;/code&gt; files back to the &lt;code&gt;gh-pages&lt;/code&gt; branch, thus updating the hosted version of the book.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Piping Within Pipes</title>
      <link>/2016/11/21/piping-within-pipes/</link>
      <pubDate>Mon, 21 Nov 2016 21:13:14 -0500</pubDate>
      
      <guid>/2016/11/21/piping-within-pipes/</guid>
      <description>


&lt;p&gt;The &lt;code&gt;magrittr&lt;/code&gt; pipe (&lt;code&gt;%&amp;gt;%&lt;/code&gt;) has revolutionised the way many people now write R code. I’ve been using R for over 7 years and the pipe has become a staple of my programming conventions. However it was recently brought to my attention that you can actually use pipes within function calls, which can make my code even more human readable. Take for example the following code.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(forcats)
library(dplyr)
gss_cat2 &amp;lt;-
  gss_cat %&amp;gt;%
  mutate(marital2 = fct_rev(fct_infreq(marital)))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Whilst this code is fairly easy to read, you can imagine how this doesn’t scale very nicely with even more nested function calls. One solution would be to use &lt;code&gt;dplyr&lt;/code&gt;’s ability to &lt;code&gt;mutate&lt;/code&gt; the same column within the &lt;code&gt;mutate&lt;/code&gt; function call to split out the code a little more.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;gss_cat3 &amp;lt;-
  gss_cat %&amp;gt;%
  mutate(
    marital2 = fct_infreq(marital),
    marital2 = fct_rev(marital2)
  )&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sure this is more readable, but it’s repeating far too much code for my liking. So, we can instead just use the pipe.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;gss_cat4 &amp;lt;-
  gss_cat %&amp;gt;%
  mutate(
    marital2 =
      marital %&amp;gt;%
      fct_infreq() %&amp;gt;%
      fct_rev()
  )&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This not only eliminates long, nested function calls but it also makes my code much more human readable! Try it yourself.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(gss_cat4) +
  geom_bar(aes(x = marital2)) +
  labs(x = &amp;quot;Marital Status&amp;quot;, y = &amp;quot;Count&amp;quot;) +
  coord_flip()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;/post/2016-11-21-pipes-in-pipes_files/figure-html/barchart-1.png&#34; width=&#34;800px&#34; /&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>About</title>
      <link>/about/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>/about/</guid>
      <description>&lt;p&gt;I am the &lt;em&gt;Chief Data Scientist&lt;/em&gt; and founder of &lt;a href=&#34;https://www.linkedin.com/company/19160182/&#34;&gt;NE Data&lt;/a&gt;. I have a demonstrated history of working and consulting across multiple industries since 2009. Skilled in R, Python, SQL and Statistical Modelling, my passion is turning business problems into technical solutions through the use of data; building pipelines; building applications; modelling; and data visualisation.&lt;/p&gt;

&lt;p&gt;I have an MSc in Statistics from Sheffield University and a BSc in Mathematics and Statistics from Plymouth University. I enjoy writing open source R code and Shiny apps; check out my work on &lt;a href=&#34;https://github.com/nathaneastwood&#34;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can &lt;a href=&#34;mailto:nathan.eastwood@icloud.com?subject=Hello&#34;&gt;email me&lt;/a&gt; or find me &lt;a href=&#34;https://twitter.com/nathaneastwood_&#34;&gt;on Twitter&lt;/a&gt; if you want to message me. I love meeting new people and talking about code so feel free to get in touch!&lt;/p&gt;

&lt;p&gt;Find me on &lt;a href=&#34;https://www.r-bloggers.com/&#34;&gt;R-Bloggers&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>