<div>I had some much needed downtime this weekend, after an exhausting week, along with some self-care – Saturday I had a one-hour deep tissue massage, which left me a little bruised but much more relaxed, and Sunday I spent a few hours in the salon chair having my color touched up, which left me much blonder. Which is why I’m a little late with my Statistics Sunday post, but today, I’m introducing another recently discovered r package: <a href="https://cran.r-project.org/web/packages/rpart/index.html">rpart</a>. Short for “recursive partitioning,” this package creates decision trees for classification, regression, and survival analyses. Today, I’m going to demonstrate using the rpart package for visualizing regression.
<p>To demonstrate this technique, I’m using my 2017 reading dataset. A reader requested I make this dataset available, which I have done – you can download it <a href="https://www.dropbox.com/s/rt5q7t5rk5z9nr2/2017_books.csv?dl=1">here</a>. <a href="http://www.deeplytrivial.com/2018/01/data-analysis-of-my-2017-reading.html">This post</a> describes the data in more detail, but the short description is that this dataset contains the 53 books I read last year, with information on book genre, page length, how long it took me to read it, and two ratings: my own rating and the average rating on Goodreads. Look for another dataset soon, containing my 2018 reading data; I made a goal of 60 books and I’ve already read 50, meaning lots more data than last year. I’m thinking of going for broke and bumping my reading goal up to 100, because apparently 60 books is not enough of a challenge for me now that I spend so much downtime reading.</p>
<p>First, I’ll load my dataset, then conduct the basic linear model I demonstrated in the post linked above.</p>
<div>
<div>
<div>
<pre><span>setwd</span><span>(</span><span>&quot;~/R&quot;</span><span>)</span><br><span>library</span><span>(tidyverse)</span><br></pre>
</div>
<div>
<pre>## Warning: Duplicated column names deduplicated: 'Author' => 'Author_1' [13]<br></pre>
</div>
<div>
<pre>## Parsed with column specification:<br>## cols(<br>##   .default = col_integer(),<br>##   Title = col_character(),<br>##   Author = col_character(),<br>##   G_Rating = col_double(),<br>##   Started = col_character(),<br>##   Finished = col_character()<br>## )<br></pre>
</div>
<div>
<pre>## See spec(...) for full column specifications.<br></pre>
</div>
<div>
<pre><span>colnames</span><span>(books)[</span><span>13</span><span>]</span> <span>&lt;-</span> <span>&quot;Author_Gender&quot;</span><br><span>myrating</span><span>&lt;-</span><span>lm</span><span>(My_Rating</span> <span>~</span> <span>Pages</span> <span>+</span> <span>Read_Time</span> <span>+</span> <span>Author_Gender</span> <span>+</span> <span>Fiction</span> <span>+</span> <span>Fantasy</span> <span>+</span> <span>Math_Stats</span> <span>+</span> <span>YA_Fic,</span> <span>data</span><span>=books)</span><br><span>summary</span><span>(myrating)</span><br></pre>
</div>
<div>
<pre>## <br>## Call:<br>## lm(formula = My_Rating ~ Pages + Read_Time + Author_Gender + <br>##     Fiction + Fantasy + Math_Stats + YA_Fic, data = books)<br>## <br>## Residuals:<br>##      Min       1Q   Median       3Q      Max <br>## -0.73120 -0.34382 -0.00461  0.24665  1.49932 <br>## <br>## Coefficients:<br>##                 Estimate Std. Error t value Pr(>|t|)    <br>## (Intercept)    3.5861211  0.2683464  13.364   &lt;2e-16 ***<br>## Pages          0.0019578  0.0007435   2.633   0.0116 *  <br>## Read_Time     -0.0244168  0.0204186  -1.196   0.2380    <br>## Author_Gender -0.1285178  0.1666207  -0.771   0.4445    <br>## Fiction        0.1052319  0.2202581   0.478   0.6351    <br>## Fantasy        0.5234710  0.2097386   2.496   0.0163 *  <br>## Math_Stats    -0.2558926  0.2122238  -1.206   0.2342    <br>## YA_Fic        -0.7330553  0.2684623  -2.731   0.0090 ** <br>## ---<br>## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1<br>## <br>## Residual standard error: 0.4952 on 45 degrees of freedom<br>## Multiple R-squared:  0.4624, Adjusted R-squared:  0.3788 <br>## F-statistic:  5.53 on 7 and 45 DF,  p-value: 0.0001233<br></pre>
</div>
</div>
</div>
<p>These analyses show that I give higher ratings for books that are longer and Fantasy genre, and lower ratings to books that are Young Adult Fiction. Now let’s see what happens if I run this same linear model through rpart. Note that this is a slightly different technique, looking for cuts that differentiate outcomes, so it will find slightly different results.</p>
<div>
<div>
<div>
<pre><span>library</span><span>(rpart)</span><br><span>tree1</span> <span>&lt;-</span> <span>rpart</span><span>(My_Rating</span> <span>~</span> <span>Pages</span> <span>+</span> <span>Read_Time</span> <span>+</span> <span>Author_Gender</span> <span>+</span> <span>Fiction</span> <span>+</span> <span>Fantasy</span> <span>+</span> <span>Math_Stats</span> <span>+</span> <span>YA_Fic,</span> <span>method</span> <span>=</span> <span>&quot;anova&quot;</span><span>,</span> <span>data</span><span>=books)</span><br><span>printcp</span><span>(tree1)</span><br></pre>
</div>
<div>
<pre>## <br>## Regression tree:<br>## rpart(formula = My_Rating ~ Pages + Read_Time + Author_Gender + <br>##     Fiction + Fantasy + Math_Stats + YA_Fic, data = books, method = &quot;anova&quot;)<br>## <br>## Variables actually used in tree construction:<br>## [1] Fantasy    Math_Stats Pages     <br>## <br>## Root node error: 20.528/53 = 0.38733<br>## <br>## n= 53 <br>## <br>##         CP nsplit rel error  xerror    xstd<br>## 1 0.305836      0   1.00000 1.03609 0.17531<br>## 2 0.092743      1   0.69416 0.76907 0.12258<br>## 3 0.022539      2   0.60142 0.71698 0.11053<br>## 4 0.010000      3   0.57888 0.74908 0.11644<br></pre>
</div>
</div>
</div>
<p>These results different somewhat. Pages is still a significant variable, as is Fantasy. But now Math_Stats (indicating books that are about mathematics or statistics, one of my top genres from last year) also is. These are the variables used by the analysis to construct my regression tree. If we look at the full summary – </p>
<div>
<div>
<div>
<pre><span>summary</span><span>(tree1)</span><br></pre>
</div>
<div>
<pre>## Call:<br>## rpart(formula = My_Rating ~ Pages + Read_Time + Author_Gender + <br>##     Fiction + Fantasy + Math_Stats + YA_Fic, data = books, method = &quot;anova&quot;)<br>##   n= 53 <br>## <br>##           CP nsplit rel error    xerror      xstd<br>## 1 0.30583640      0 1.0000000 1.0360856 0.1753070<br>## 2 0.09274251      1 0.6941636 0.7690729 0.1225752<br>## 3 0.02253938      2 0.6014211 0.7169813 0.1105294<br>## 4 0.01000000      3 0.5788817 0.7490758 0.1164386<br>## <br>## Variable importance<br>##      Pages    Fantasy    Fiction     YA_Fic Math_Stats  Read_Time <br>##         62         18          8          6          4          3 <br>## <br>## Node number 1: 53 observations,    complexity param=0.3058364<br>##   mean=4.09434, MSE=0.3873265 <br>##   left son=2 (9 obs) right son=3 (44 obs)<br>##   Primary splits:<br>##       Pages         &lt; 185 to the left,  improve=0.30583640, (0 missing)<br>##       Fiction       &lt; 0.5 to the left,  improve=0.24974560, (0 missing)<br>##       Fantasy       &lt; 0.5 to the left,  improve=0.20761810, (0 missing)<br>##       Math_Stats    &lt; 0.5 to the right, improve=0.20371790, (0 missing)<br>##       Author_Gender &lt; 0.5 to the right, improve=0.02705187, (0 missing)<br>## <br>## Node number 2: 9 observations<br>##   mean=3.333333, MSE=0.2222222 <br>## <br>## Node number 3: 44 observations,    complexity param=0.09274251<br>##   mean=4.25, MSE=0.2784091 <br>##   left son=6 (26 obs) right son=7 (18 obs)<br>##   Primary splits:<br>##       Fantasy    &lt; 0.5 to the left,  improve=0.15541600, (0 missing)<br>##       Fiction    &lt; 0.5 to the left,  improve=0.12827990, (0 missing)<br>##       Math_Stats &lt; 0.5 to the right, improve=0.10487750, (0 missing)<br>##       Pages      &lt; 391 to the left,  improve=0.05344995, (0 missing)<br>##       Read_Time  &lt; 7.5 to the right, improve=0.04512078, (0 missing)<br>##   Surrogate splits:<br>##       Fiction   &lt; 0.5 to the left,  agree=0.773, adj=0.444, (0 split)<br>##       YA_Fic    &lt; 0.5 to the left,  agree=0.727, adj=0.333, (0 split)<br>##       Pages     &lt; 370 to the left,  agree=0.682, adj=0.222, (0 split)<br>##       Read_Time &lt; 3.5 to the right, agree=0.659, adj=0.167, (0 split)<br>## <br>## Node number 6: 26 observations,    complexity param=0.02253938<br>##   mean=4.076923, MSE=0.2248521 <br>##   left son=12 (7 obs) right son=13 (19 obs)<br>##   Primary splits:<br>##       Math_Stats    &lt; 0.5 to the right, improve=0.079145230, (0 missing)<br>##       Pages         &lt; 364 to the left,  improve=0.042105260, (0 missing)<br>##       Fiction       &lt; 0.5 to the left,  improve=0.042105260, (0 missing)<br>##       Read_Time     &lt; 5.5 to the left,  improve=0.016447370, (0 missing)<br>##       Author_Gender &lt; 0.5 to the right, improve=0.001480263, (0 missing)<br>## <br>## Node number 7: 18 observations<br>##   mean=4.5, MSE=0.25 <br>## <br>## Node number 12: 7 observations<br>##   mean=3.857143, MSE=0.4081633 <br>## <br>## Node number 13: 19 observations<br>##   mean=4.157895, MSE=0.132964<br></pre>
</div>
</div>
</div>
<p>we see that Fiction, YA_Fic, and Read_Time were also significant variables. The problem is that there is multicollinearity between Fiction, Fantasy, Math_Stats, and YA_Fic. All Fantasy and YA_Fic books are Fiction, while all Math_Stats books are not Fiction. And all YA_Fic books I read were Fantasy. This is probably why the tree didn’t use Fiction or YA_Fic. I’m not completely clear on why Read_Time didn’t end up in the regression tree, but it may be because my read time was pretty constant among the different splits and didn’t add any new information to the tree. If I were presenting these results somewhere other than my blog, I’d probably want to do some follow-up analyses to confirm this fact.</p>
<p>Now the fun part: let’s plot our regression tree:</p>
<div>
<div>
<div>
<pre><span>plot</span><span>(tree1,</span> <span>uniform</span> <span>=</span> <span>TRUE</span><span>,</span> <span>main</span> <span>=</span> <span>&quot;Regression Tree for My Goodreads Ratings&quot;</span><span>)</span><br><span>text</span><span>(tree1,</span> <span>use.n</span> <span>=</span> <span>TRUE</span><span>,</span> <span>all</span> <span>=</span> <span>TRUE</span><span>,</span> <span>cex</span> <span>=</span> <span>0.8</span><span>)</span><br></pre>
</div>
</div>
<div><a rel="nofollow" href="https://i2.wp.com/1.bp.blogspot.com/-0yqOWxHEGPQ/W4QedVlw5NI/AAAAAAAANro/Pp-oSMVe5gcbi3u2-bMyI1AwZZ1J1XzkACLcBGAs/s1600/unnamed-chunk-4-1.png?ssl=1" target="_blank"><img border="0" src="https://i1.wp.com/1.bp.blogspot.com/-0yqOWxHEGPQ/W4QedVlw5NI/AAAAAAAANro/Pp-oSMVe5gcbi3u2-bMyI1AwZZ1J1XzkACLcBGAs/s320/unnamed-chunk-4-1.png?resize=320%2C320&ssl=1" data-original-width="450" width="320" data-original-height="504" data-recalc-dims="1" height="320"></a></div>
</div>
<p>This tree shows that, before taking into account anything, my average book rating was 4.09. If a book is shorter than 185 pages (9 books in my dataset), it’s average rating was 3.33. For longer books (44), the average rating was 4.25. But there’s more to it than that. For non-Fantasy books (26), the average was 4.08, while the Fantasy (18 books) average was 4.5. If the book was Math_Stats (7), I gave it an average of 3.86, and if it was not Math_Stats (19), the average was 4.16. (Unfortunately, R cuts off the bottom part of the plot.) </p>
<p>While this plot is great for a quick visualization, I can make a nicer looking plot (which doesn’t cut off the bottom text) as a PostScript file.</p>
<div>
<div>
<div>
<pre><span>post</span><span>(tree1,</span> <span>file</span> <span>=</span> <span>&quot;mytree.ps&quot;</span><span>,</span><br>        <span>title</span> <span>=</span> <span>&quot;Regression Tree for Rating&quot;</span><span>)</span><br></pre>
</div>
</div>
</div>
<p>I converted that to a PDF, which you can view <a rel="nofollow" href="https://www.dropbox.com/s/riszqh48hzyg2cl/mytree.pdf?dl=0" target="_blank">here</a>.</p>
<p>Hope you enjoyed this post! Have any readers used this technique before? Any thoughts or applications you’d like to share? (Self-promotion highly encouraged!) </p>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="http://www.deeplytrivial.com/2018/08/statistics-sunday-visualizing-regression.html"> Deeply Trivial</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/mzr0nsUANTA" height="1"></a></div></div>