Welcome to the fifteenth post in the rarely rational R rambling series, or R4 for short. There are two posts I have been meaning to get out for a bit, and hope to get to shortly---but in the meantime we are going start something else.
Another longer-running idea I had was to present some simple application cases with (one or more) side-by-side code comparisons. Why? Well at times it feels like R, and the R community, are being split. You're either with one (increasingly &quot;religious&quot; in their defense of their deemed-superior approach) side, or the other. And that is of course utter nonsense. It's all R after all.
Programming, just like other fields using engineering methods and thinking, is about making choices, and trading off between certain aspects. A simple example is the fairly well-known trade-off between memory use and speed: think e.g. of a hash map allowing for faster lookup at the cost of some more memory. Generally speaking, solutions are rarely limited to just one way, or just one approach. So if pays off to know your tools, and choose wisely among all available options. Having choices is having options, and those tend to have non-negative premiums to take advantage off. Locking yourself into one and just one paradigm can never be better.
In that spirit, I want to (eventually) show a few simple comparisons of code being done two distinct ways.
One obvious first candidate for this is the gunsales repository with some R code which backs an earlier NY Times article. I got involved for a similar reason, and updated the code from its initial form. Then again, this project also helped motivate what we did later with the x13binary package which permits automated installation of the X13-ARIMA-SEATS binary to support Christoph's excellent seasonal CRAN package (and website) for which we now have a forthcoming JSS paper. But the actual code example is not that interesting / a bit further off the mainstream because of the more specialised seasonal ARIMA modeling.
But then this week I found a much simpler and shorter example, and quickly converted its code. The code comes from the inaugural datascience 1 lesson at the Crosstab, a fabulous site by G. Elliot Morris (who may be the highest-energy undergrad I have come across lately) focusssed on political polling, forecasts, and election outcomes. Lesson 1 is a simple introduction, and averages some polls of the 2016 US Presidential Election.
Complete Code using Approach &quot;TV&quot;
Elliot does a fine job walking the reader through his code so I will be brief and simply quote it in one piece:
## Getting the polls
library(readr)
polls_2016 %
summarise(Clinton = mean(Clinton),
Trump = mean(Trump))
library(zoo)
rolling_average %
mutate(Clinton.Margin = Clinton-Trump,
Clinton.Avg = rollapply(Clinton.Margin,width=14,
FUN=function(x){mean(x, na.rm=TRUE)},
by=1, partial=TRUE, fill=NA, align=&quot;right&quot;))
library(ggplot2)
ggplot(rolling_average)+
geom_line(aes(x=end_date,y=Clinton.Avg),col=&quot;blue&quot;) +
geom_point(aes(x=end_date,y=Clinton.Margin))
It uses five packages to i) read some data off them interwebs, ii) then filters / subsets / modifies it leading to a right (outer) join with itself before iv) averaging per-day polls first and then creates rolling averages over 14 days before v) plotting. Several standard verbs are used: filter(), mutate(), right_join(), group_by(), and summarise(). One non-verse function is rollapply() which comes from zoo, a popular package for time-series data.
Complete Code using Approach &quot;DT&quot;
As I will show below, we can do the same with fewer packages as data.table covers the reading, slicing/dicing and time conversion. We still need zoo for its rollapply() and of course the same plotting code:
## Getting the polls
library(data.table)
pollsDT rdin dtin R__ library(dplyr)
R__ library(lubridate)
R__ library(zoo)
R__ R__ transformTV %
+ summarise(Clinton = mean(Clinton),
+ Trump = mean(Trump))
+ + rolling_average %
+ mutate(Clinton.Margin = Clinton-Trump,
+ Clinton.Avg = rollapply(Clinton.Margin,width=14,
+ FUN=function(x){mean(x, na.rm=TRUE)}, + by=1, partial=TRUE, fill=NA, align=&quot;right&quot;))
+ }
R__ R__ transformDT