<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/data-science-for-business-time-series-forecasting-part-3-forecasting-with-facebooks-prophet/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://shiring.github.io/forecasting/2017/06/13/retail_forcasting_part3"> Shirin's playgRound</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>In my last two posts (<a rel="nofollow" href="https://shiring.github.io/forecasting/2017/05/28/retail_forcasting_part1" target="_blank">Part 1</a> and <a rel="nofollow" href="https://shiring.github.io/forecasting/2017/06/09/retail_forcasting_part2" target="_blank">Part 2</a>), I explored time series forecasting with the <strong>timekit</strong> package.</p>
<p>In this post, I want to compare how <a rel="nofollow" href="https://facebookincubator.github.io/prophet/" target="_blank">Facebook’s prophet</a> performs on the same dataset.</p>
<p></p>
<p>Predicting future events/sales/etc. isn’t trivial for a number of reasons and different algorithms use different approaches to handle these problems. Time series data does not behave like a regular numeric vector, because months don’t have the same number of days, weekends and holidays differ between years, etc. Because of this, we often have to deal with multiple layers of seasonality (i.e. weekly, monthly, yearly, irregular holidays, etc.). Regularly missing days, like weekends, are easier to incorporate into time series models than irregularly missing days.</p>
<p></p>
<p><strong>Timekit</strong> uses a time series signature for modeling, which we used as features to build our model of choice (e.g. a linear model). This model was then used for predicting future dates.</p>
<p><strong>Prophet</strong> is Facebook’s time series forecasting algorithm that was just recently released as open source software with an implementation in R.</p>
<blockquote>
<p>“<a rel="nofollow" href="https://facebookincubator.github.io/prophet/" target="_blank">Prophet</a> is a procedure for forecasting time series data. It is based on an additive model where non-linear trends are fit with yearly and weekly seasonality, plus holidays. It works best with daily periodicity data with at least one year of historical data. Prophet is robust to missing data, shifts in the trend, and large outliers.”</p>
</blockquote>
<p>(I am not going to discuss <strong>forecast</strong> and ARIMA or other models because they are quite well established with lots and lots of excellent tutorials out there.)</p>
<p></p>
<h3>Training and Test data</h3>
<p>I am using the same training and test intervals as in <a rel="nofollow" href="https://shiring.github.io/forecasting/2017/06/09/retail_forcasting_part2" target="_blank">my last post using <strong>timekit</strong></a>.</p>
<p>Just as with <strong>timekit</strong>, <strong>prophet</strong> starts with a data frame that consists of a date column and the respective response variable for each date.</p>
<div>
<pre><code><span>library</span><span>(</span><span>prophet</span><span>)</span><span>
</span><span>library</span><span>(</span><span>tidyverse</span><span>)</span><span>
</span><span>library</span><span>(</span><span>tidyquant</span><span>)</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>retail_p_day</span><span> </span><span>&lt;-</span><span> </span><span>retail_p_day</span><span> </span><span>%>%</span><span>
</span><span>mutate</span><span>(</span><span>model</span><span> </span><span>=</span><span> </span><span>ifelse</span><span>(</span><span>day</span><span> </span><span>&lt;=</span><span> </span><span>&quot;2011-11-01&quot;</span><span>,</span><span> </span><span>&quot;train&quot;</span><span>,</span><span> </span><span>&quot;test&quot;</span><span>))</span><span>
</span><span>train</span><span> </span><span>&lt;-</span><span> </span><span>filter</span><span>(</span><span>retail_p_day</span><span>,</span><span> </span><span>model</span><span> </span><span>==</span><span> </span><span>&quot;train&quot;</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>select</span><span>(</span><span>day</span><span>,</span><span> </span><span>sum_income</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>rename</span><span>(</span><span>ds</span><span> </span><span>=</span><span> </span><span>day</span><span>,</span><span>
</span><span>y</span><span> </span><span>=</span><span> </span><span>sum_income</span><span>)</span><span>
</span><span>test</span><span> </span><span>&lt;-</span><span> </span><span>filter</span><span>(</span><span>retail_p_day</span><span>,</span><span> </span><span>model</span><span> </span><span>==</span><span> </span><span>&quot;test&quot;</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>select</span><span>(</span><span>day</span><span>,</span><span> </span><span>sum_income</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>rename</span><span>(</span><span>ds</span><span> </span><span>=</span><span> </span><span>day</span><span>)</span><span>
</span></code></pre>
</div>
<p></p>
<h3>Model building</h3>
<p>In contrast to <strong>timekit</strong>, we do not “manually” augment the time series signature in <strong>prophet</strong>, we can directly feed our input data to the <code>prophet()</code> function (check the function help for details on optional parameters).</p>
<p>To make it comparable, I am feeding the same list of irregularly missing days to the <code>prophet()</code> function. As discussed in the last post, I chose not to use a list of holidays because the holidays in the observation period poorly matched the days that were actually missing.</p>
<div>
<pre><code><span>off_days</span><span> </span><span>&lt;-</span><span> </span><span>data.frame</span><span>(</span><span>ds</span><span> </span><span>=</span><span> </span><span>as.Date</span><span>(</span><span>c</span><span>(</span><span>&quot;2010-12-24&quot;</span><span>,</span><span> </span><span>&quot;2010-12-25&quot;</span><span>,</span><span> </span><span>&quot;2010-12-26&quot;</span><span>,</span><span> </span><span>&quot;2010-12-27&quot;</span><span>,</span><span> </span><span>&quot;2010-12-28&quot;</span><span>,</span><span> </span><span>&quot;2010-12-29&quot;</span><span>,</span><span> </span><span>&quot;2010-12-30&quot;</span><span>,</span><span> </span><span>&quot;2010-01-01&quot;</span><span>,</span><span> </span><span>&quot;2010-01-02&quot;</span><span>,</span><span> </span><span>&quot;2010-01-03&quot;</span><span>,</span><span>
</span><span>&quot;2011-04-22&quot;</span><span>,</span><span> </span><span>&quot;2011-04-23&quot;</span><span>,</span><span> </span><span>&quot;2011-04-24&quot;</span><span>,</span><span> </span><span>&quot;2011-04-25&quot;</span><span>,</span><span> </span><span>&quot;2011-05-02&quot;</span><span>,</span><span> </span><span>&quot;2011-05-30&quot;</span><span>,</span><span> </span><span>&quot;2011-08-29&quot;</span><span>,</span><span> </span><span>&quot;2011-04-29&quot;</span><span>,</span><span> </span><span>&quot;2011-04-30&quot;</span><span>)))</span><span> </span><span>%>%</span><span>
</span><span>mutate</span><span>(</span><span>holiday</span><span> </span><span>=</span><span> </span><span>paste0</span><span>(</span><span>&quot;off_day_&quot;</span><span>,</span><span> </span><span>seq_along</span><span>(</span><span>1</span><span>:</span><span>length</span><span>(</span><span>ds</span><span>))))</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>prophet_model_test</span><span> </span><span>&lt;-</span><span> </span><span>prophet</span><span>(</span><span>train</span><span>,</span><span> </span><span>growth</span><span> </span><span>=</span><span> </span><span>&quot;linear&quot;</span><span>,</span><span> </span><span># growth curve trend
</span><span> </span><span>n.changepoints</span><span> </span><span>=</span><span> </span><span>100</span><span>,</span><span> </span><span># Prophet automatically detects changes in trends by selecting changepoints from the data
</span><span> </span><span>yearly.seasonality</span><span> </span><span>=</span><span> </span><span>FALSE</span><span>,</span><span> </span><span># yearly seasonal component using Fourier series
</span><span> </span><span>weekly.seasonality</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>,</span><span> </span><span># weekly seasonal component using dummy variables
</span><span> </span><span>holidays</span><span> </span><span>=</span><span> </span><span>off_days</span><span>)</span><span> </span></code></pre>
</div>
<div>
<pre><code>## Initial log joint probability = -8.3297
## Optimization terminated normally: 
##   Convergence detected: relative gradient magnitude is below tolerance
</code></pre>
</div>
<p></p>
<h3>Predicting test data</h3>
<p>With our model, we can now predict on the test data and compare the predictions with the actual values.</p>
<div>
<pre><code><span>forecast_test</span><span> </span><span>&lt;-</span><span> </span><span>predict</span><span>(</span><span>prophet_model_test</span><span>,</span><span> </span><span>test</span><span>)</span><span>
</span></code></pre>
</div>
<p></p>
<p>Just as with <strong>timekit</strong>, I want to have a look at the residuals. Compared to <strong>timekit</strong>, the residuals actually look almost identical…</p>
<div>
<pre><code><span>forecast_test</span><span> </span><span>%>%</span><span>
</span><span>mutate</span><span>(</span><span>resid</span><span> </span><span>=</span><span> </span><span>sum_income</span><span> </span><span>-</span><span> </span><span>yhat</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>ggplot</span><span>(</span><span>aes</span><span>(</span><span>x</span><span> </span><span>=</span><span> </span><span>ds</span><span>,</span><span> </span><span>y</span><span> </span><span>=</span><span> </span><span>resid</span><span>))</span><span> </span><span>+</span><span>
</span><span>geom_hline</span><span>(</span><span>yintercept</span><span> </span><span>=</span><span> </span><span>0</span><span>,</span><span> </span><span>color</span><span> </span><span>=</span><span> </span><span>&quot;red&quot;</span><span>)</span><span> </span><span>+</span><span>
</span><span>geom_point</span><span>(</span><span>alpha</span><span> </span><span>=</span><span> </span><span>0.5</span><span>,</span><span> </span><span>color</span><span> </span><span>=</span><span> </span><span>palette_light</span><span>()[[</span><span>1</span><span>]])</span><span> </span><span>+</span><span>
</span><span>geom_smooth</span><span>()</span><span> </span><span>+</span><span>
</span><span>theme_tq</span><span>()</span><span>
</span></code></pre>
</div>
<p><img alt="" src="https://i1.wp.com/shiring.github.io/forecasting/2017/06/13/retail_forcasting_part3_files/figure-markdown_github/unnamed-chunk-7-1.png?w=456&ssl=1" data-recalc-dims="1"></p>
<p></p>
<p>… As does the comparison plot. So, here it seems that <strong>prophet</strong> built a model that is basically identical to the linear model I used with <strong>timekit</strong>.</p>
<div>
<pre><code><span>forecast_test</span><span> </span><span>%>%</span><span>
</span><span>gather</span><span>(</span><span>x</span><span>,</span><span> </span><span>y</span><span>,</span><span> </span><span>sum_income</span><span>,</span><span> </span><span>yhat</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>ggplot</span><span>(</span><span>aes</span><span>(</span><span>x</span><span> </span><span>=</span><span> </span><span>ds</span><span>,</span><span> </span><span>y</span><span> </span><span>=</span><span> </span><span>y</span><span>,</span><span> </span><span>color</span><span> </span><span>=</span><span> </span><span>x</span><span>))</span><span> </span><span>+</span><span>
</span><span>geom_point</span><span>(</span><span>alpha</span><span> </span><span>=</span><span> </span><span>0.5</span><span>)</span><span> </span><span>+</span><span>
</span><span>geom_line</span><span>(</span><span>alpha</span><span> </span><span>=</span><span> </span><span>0.5</span><span>)</span><span> </span><span>+</span><span>
</span><span>scale_color_manual</span><span>(</span><span>values</span><span> </span><span>=</span><span> </span><span>palette_light</span><span>())</span><span> </span><span>+</span><span>
</span><span>theme_tq</span><span>()</span><span>
</span></code></pre>
</div>
<p><img alt="" src="https://i2.wp.com/shiring.github.io/forecasting/2017/06/13/retail_forcasting_part3_files/figure-markdown_github/unnamed-chunk-8-1.png?w=456&ssl=1" data-recalc-dims="1"></p>
<p></p>
<h3>Predicting future sales</h3>
<p>Now, let’s see whether the future predictions will be identical as well.</p>
<p>Just like with <strong>timekit</strong>, I am using a future time series of 300 days. Here, we see a slight difference in how we generate the future time series: with <strong>timekit</strong> I could use the entire index of observed dates, together with the list of missing days, while <strong>prophet</strong> uses the forecasting model that was generated for comparing the test data, i.e. it only considers the dates from the training set. We could built a new model with the entire dataset but this would then be different to how I approached the modeling with <strong>timekit</strong>.</p>
<div>
<pre><code><span>future</span><span> </span><span>&lt;-</span><span> </span><span>make_future_dataframe</span><span>(</span><span>prophet_model_test</span><span>,</span><span> </span><span>periods</span><span> </span><span>=</span><span> </span><span>300</span><span>)</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>forecast</span><span> </span><span>&lt;-</span><span> </span><span>predict</span><span>(</span><span>prophet_model_test</span><span>,</span><span> </span><span>future</span><span>)</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>plot</span><span>(</span><span>prophet_model_test</span><span>,</span><span> </span><span>forecast</span><span>)</span><span> </span><span>+</span><span>
</span><span>theme_tq</span><span>()</span><span>
</span></code></pre>
</div>
<p><img alt="" src="https://i0.wp.com/shiring.github.io/forecasting/2017/06/13/retail_forcasting_part3_files/figure-markdown_github/unnamed-chunk-12-1.png?w=456&ssl=1" data-recalc-dims="1"></p>
<p>Interestingly, <strong>prophet</strong>’s forecast is distinctly different from <strong>timekit</strong>’s, despite identical performance on test samples! While <strong>timekit</strong> predicted a drop at the beginning of the year (similar to the training period), <strong>prophet</strong> predicts a steady increase in the future. It looks like <strong>timekit</strong> put more weight on the overall pattern during the training period, while <strong>prophet</strong> seems to put more weight on the last months, which showed a rise in net income.</p>
<hr>
<p></p>
<div>
<pre><code><span>sessionInfo</span><span>()</span><span>
</span></code></pre>
</div>
<div>
<pre><code>## R version 3.4.0 (2017-04-21)
## Platform: x86_64-w64-mingw32/x64 (64-bit)
## Running under: Windows 7 x64 (build 7601) Service Pack 1
## 
## Matrix products: default
## 
## locale:
## [1] LC_COLLATE=English_United States.1252 
## [2] LC_CTYPE=English_United States.1252   
## [3] LC_MONETARY=English_United States.1252
## [4] LC_NUMERIC=C                          
## [5] LC_TIME=English_United States.1252    
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] tidyquant_0.5.1               quantmod_0.4-8               
##  [3] TTR_0.23-1                    PerformanceAnalytics_1.4.3541
##  [5] xts_0.9-7                     zoo_1.8-0                    
##  [7] lubridate_1.6.0               dplyr_0.5.0                  
##  [9] purrr_0.2.2.2                 readr_1.1.1                  
## [11] tidyr_0.6.3                   tibble_1.3.1                 
## [13] ggplot2_2.2.1                 tidyverse_1.1.1              
## [15] prophet_0.1.1                 Rcpp_0.12.11                 
## 
## loaded via a namespace (and not attached):
##  [1] rstan_2.15.1         reshape2_1.4.2       haven_1.0.0         
##  [4] lattice_0.20-35      colorspace_1.3-2     htmltools_0.3.6     
##  [7] stats4_3.4.0         yaml_2.1.14          rlang_0.1.1         
## [10] foreign_0.8-68       DBI_0.6-1            modelr_0.1.0        
## [13] readxl_1.0.0         plyr_1.8.4           stringr_1.2.0       
## [16] Quandl_2.8.0         munsell_0.4.3        gtable_0.2.0        
## [19] cellranger_1.1.0     rvest_0.3.2          codetools_0.2-15    
## [22] psych_1.7.5          evaluate_0.10        labeling_0.3        
## [25] inline_0.3.14        knitr_1.16           forcats_0.2.0       
## [28] parallel_3.4.0       broom_0.4.2          scales_0.4.1        
## [31] backports_1.0.5      StanHeaders_2.15.0-1 jsonlite_1.5        
## [34] gridExtra_2.2.1      mnormt_1.5-5         hms_0.3             
## [37] digest_0.6.12        stringi_1.1.5        grid_3.4.0          
## [40] rprojroot_1.2        tools_3.4.0          magrittr_1.5        
## [43] lazyeval_0.2.0       xml2_1.1.1           extraDistr_1.8.5    
## [46] assertthat_0.2.0     rmarkdown_1.5        httr_1.2.1          
## [49] R6_2.2.1             nlme_3.1-131         compiler_3.4.0
</code></pre>
</div>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="https://shiring.github.io/forecasting/2017/06/13/retail_forcasting_part3"> Shirin's playgRound</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...

	<img width="1" alt="" src="http://feeds.feedburner.com/~r/RBloggers/~4/t3eVIuTW0bk" height="1"></a></div>