<p><div><div><div><div data-width="100" data-show-faces="false" data-send="true" data-layout="button_count" data-height="21" data-href="https://www.r-bloggers.com/from-descriptive-to-prescriptive-analytics/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="http://flovv.github.io/From_descritpive_to_prescriptive/"> Florian Teschner</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>Predominately data science projects deal with descriptive statistics. The common theme (especially on this blog) is to gather a dataset, visualize and describe it. The toolset consists of a combination of machine learning, descriptive statistics and (gg-)plots.<br>
This time I want to go a step further; from descriptive to prescriptive analytics.<br>
The goal is to optimize a fantasy football team. To be more precise the task at hand is to select a set of players while keeping within the budget (e.g. a typical knapsack problem). For that I first gathered some fantasy football data from comunio.de</p>
<p><img alt="plot of chunk unnamed-chunk-2" src="https://i0.wp.com/flovv.github.io/figures/post18/unnamed-chunk-2-1.png?w=456" data-recalc-dims="1"></p>
<p>The plot above nicely illustrates the data. It basically contains of a list of players (488) which hold one of four positions and are characterized by two basic variables; (a) the market value, – for how much a player can be bought on the fantasy market, and (b) the Score which indicates how well a player has performed.</p>
<p>A simple optimization problem is to figure out how to maximize the number of points while keeping within the team budget. There are two more constraints on the line-up, each team needs to have exactly one keeper and a dynamic number of players on the defense, midfield and offensive positions. As players might be injured during the season, let’s simplify the line-up constraints and the maximum for each position is 1 keeper, 5 defender, 5 midfielder and 3 scorer. Additionally, in total a team consists of exactly 13 players.</p>
<p>How can we setup this optimization problem in R?<br>
In contrast to most formal definitions, I will start defining the solution backwards.</p>
<p>First, let’s define the objective; it is to maximize team score. The decision is which player to pick to maximize the score. Hence the decision variables (x1 – x488) are binary and are multiplied with the individual player score.<br>
The “simple” dataframe contains all players with their market value, score and position.<br>
In order to setup the objective vector I simply take the “Score” vector.<br>
Then I define the right-hand side of the constraints using two vectors. It is important that the positions align (e.g. the 1 refers to the keeper position which should equal.)</p>
<figure>
<pre><code data-lang="r"><span>library</span><span>(</span><span>lpSolve</span><span>)</span><span>
</span><span>f.obj</span><span> </span><span>&lt;-</span><span> </span><span>simple</span><span>$</span><span>Score</span><span> </span><span>### objective! </span><span> </span><span>## constraints #budget 20 mio, 13 players, 1 keeper, 5 defender, ... 3 scorer
</span><span>f.rhs</span><span> </span><span>&lt;-</span><span> </span><span>c</span><span>(</span><span>20000000</span><span>,</span><span> </span><span>13</span><span>,</span><span> </span><span>1</span><span>,</span><span> </span><span>5</span><span>,</span><span> </span><span>5</span><span>,</span><span> </span><span>3</span><span>)</span><span>
</span><span>#coresponding budget needs to lower than defined above, exactly 1 keeper
</span><span>f.dir</span><span> </span><span>&lt;-</span><span> </span><span>c</span><span>(</span><span>&quot;&lt;=&quot;</span><span>,</span><span> </span><span>&quot;&lt;=&quot;</span><span>,</span><span> </span><span>&quot;=&quot;</span><span>,</span><span> </span><span>&quot;&lt;=&quot;</span><span>,</span><span> </span><span>&quot;&lt;=&quot;</span><span> </span><span>,</span><span>&quot;&lt;=&quot;</span><span>)</span></code></pre>
</figure>
<p>Next I need to setup the left-hand side accordingly. In order to keep the right order (matching the left hand side), I start with the market value of each player. The sum over the decision variables times the individual market value should be lower than 20 Million.<br>
Than I define a player vector set to 1 equal to the size of the dataframe.</p>
<figure>
<pre><code data-lang="r"><span>f.con</span><span> </span><span>&lt;-</span><span> </span><span>t</span><span>(</span><span>simple</span><span>$</span><span>MarketValue</span><span>)</span><span> </span><span>### constraints max MV &lt;= Budget
</span><span>player</span><span> </span><span>&lt;-</span><span> </span><span>rep</span><span>(</span><span>1</span><span>,</span><span> </span><span>nrow</span><span>(</span><span>simple</span><span>))</span><span> </span><span>## constraints max number of players!
</span><span>f.con</span><span> </span><span>&lt;-</span><span> </span><span>rbind</span><span>(</span><span>f.con</span><span>,</span><span> </span><span>player</span><span>)</span></code></pre>
</figure>
<p>Finally, for the left-hand side, I need to take into consideration the position each player holds. A nice function allows to one-hot encode the dummy “Position” variable in a suitable matrix.</p>
<figure>
<pre><code data-lang="r"><span>## constrain that per postion can only be a certain number of players be set up. (e.g. just one keeper)
## define matrix - as a one hot (dummy coding what position the player holds)
</span><span>A</span><span> </span><span>&lt;-</span><span> </span><span>as.data.frame</span><span>(</span><span>model.matrix</span><span>(</span><span>MarketValue</span><span> </span><span>~</span><span> </span><span>Position</span><span> </span><span>-1</span><span>,</span><span> </span><span>simple</span><span>)</span><span> </span><span>)</span><span>
</span><span>f.con</span><span> </span><span>&lt;-</span><span> </span><span>rbind</span><span>(</span><span>f.con</span><span>,</span><span> </span><span>t</span><span>(</span><span>as.matrix</span><span>(</span><span>A</span><span>)))</span></code></pre>
</figure>
<p>That brings us to the nice part: solving the linear program using lpsolve.<br>
The solution represents the decision variables, indicating which of the player should be bought.<br>
Applying that back to the dataframe, I get the optimal score, market value and the name of players to be bought.</p>
<figure>
<pre><code data-lang="r"><span>### solve the problem
</span><span>solved</span><span>&lt;-</span><span> </span><span>lp</span><span>(</span><span>&quot;max&quot;</span><span>,</span><span> </span><span>f.obj</span><span>,</span><span> </span><span>f.con</span><span>,</span><span> </span><span>f.dir</span><span>,</span><span> </span><span>f.rhs</span><span>,</span><span> </span><span>all.bin</span><span>=</span><span>TRUE</span><span>)</span><span> </span><span>## just binary decision variables!
</span><span> </span><span>###################output!
</span><span>simple</span><span>$</span><span>buy</span><span> </span><span>&lt;-</span><span> </span><span>solved</span><span>$</span><span>solution</span><span>
</span><span>sum</span><span>(</span><span>out</span><span>[</span><span>out</span><span>$</span><span>buy</span><span> </span><span>==</span><span> </span><span>1</span><span>,]</span><span>$</span><span>MarketValue</span><span>)</span><span> </span><span>##</span><span> </span><span>what</span><span> </span><span>is</span><span> </span><span>the</span><span> </span><span>Budget</span></code></pre>
</figure>
<figure>
<pre><code data-lang="text">## [1] 19800000</code></pre>
</figure>
<figure>
<pre><code data-lang="r"><span>sum</span><span>(</span><span>out</span><span>[</span><span>out</span><span>$</span><span>buy</span><span> </span><span>==</span><span> </span><span>1</span><span>,]</span><span>$</span><span>Score</span><span>)</span><span> </span><span>##</span><span> </span><span>what</span><span> </span><span>is</span><span> </span><span>the</span><span> </span><span>Score</span></code></pre>
</figure>
<figure>
<pre><code data-lang="text">## [1] 784</code></pre>
</figure>
<figure>
<pre><code data-lang="r"><span>sum</span><span>(</span><span>out</span><span>[</span><span>out</span><span>$</span><span>buy</span><span> </span><span>==</span><span> </span><span>1</span><span>,]</span><span>$</span><span>buy</span><span>)</span><span> </span><span>##</span><span> </span><span>number</span><span> </span><span>of</span><span> </span><span>players</span><span> </span><span>bought</span></code></pre>
</figure>
<figure>
<pre><code data-lang="text">## [1] 13</code></pre>
</figure>
<figure>
<pre><code data-lang="r"><span>paste</span><span>(</span><span>out</span><span>[</span><span>out</span><span>$</span><span>buy</span><span> </span><span>==</span><span> </span><span>1</span><span>,]</span><span>$</span><span>Name</span><span>,</span><span> </span><span>collapse</span><span>=</span><span>&quot;, &quot;</span><span>)</span><span> </span></code></pre>
</figure>
<figure>
<pre><code data-lang="text">## [1] &quot;Badstuber, Baier, Balitsch, Ede, Gomez, Hasebe, Klavan, Krmas, Piszczek, R. Schäfer, Soto, Svensson, Werner&quot;</code></pre>
</figure>
<p>That’s it. Instead of just describing the dataset and figuring out which players performed well according to some metric, I used just ~40 lines of code to get the optimal result while keeping within the constraints. On a general note; while these problems are pretty common in various industries, the problem class and solution is vastly undervalued by data scientists and online courses.</p>
<p>Well ordered source code:<br>
</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://flovv.github.io/From_descritpive_to_prescriptive/"> Florian Teschner</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 title="The R Project for Statistical Computing" rel="nofollow" href="https://www.r-project.org/">R</a> news and <a title="R tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/tutorial">tutorials</a> on topics such as: <a title="Data science" rel="nofollow" href="https://www.r-bloggers.com/search/data%20science">Data science</a>, <a title="Big Data" rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data">Big Data, <a title="R jobs" rel="nofollow" href="https://www.r-users.com/">R jobs</a>, visualization (<a title="ggplot and ggplot2 tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2">ggplot2</a>, <a title="Boxplots using lattice and ggplot2 tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/boxplot">Boxplots</a>, <a title="Maps and gis" rel="nofollow" href="https://www.r-bloggers.com/search/map">maps</a>, <a title="Animation in R" rel="nofollow" href="https://www.r-bloggers.com/search/animation">animation</a>), programming (<a title="RStudio IDE for R" rel="nofollow" href="https://www.r-bloggers.com/search/RStudio">RStudio</a>, <a title="Sweave and literate programming" rel="nofollow" href="https://www.r-bloggers.com/search/sweave">Sweave</a>, <a title="LaTeX in R" rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX">LaTeX</a>, <a title="SQL and databases" rel="nofollow" href="https://www.r-bloggers.com/search/SQL">SQL</a>, <a title="Eclipse IDE for R" rel="nofollow" href="https://www.r-bloggers.com/search/eclipse">Eclipse</a>, <a title="git and github, Version Control System" rel="nofollow" href="https://www.r-bloggers.com/search/git">git</a>, <a title="Large data in R using Hadoop" rel="nofollow" href="https://www.r-bloggers.com/search/hadoop">hadoop</a>, <a title="Web Scraping of google, facebook, yahoo, twitter and more using R" rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping">Web Scraping</a>) statistics (<a title="Regressions and ANOVA analysis tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/regression">regression</a>, <a title="principal component analysis tutorial" rel="nofollow" href="https://www.r-bloggers.com/search/PCA">PCA</a>, <a title="Time series" rel="nofollow" href="https://www.r-bloggers.com/search/time+series">time series</a>, <a title="finance trading" rel="nofollow" href="https://www.r-bloggers.com/search/trading">trading</a>) and more...
<img height="1" alt="" width="1" src="http://feeds.feedburner.com/~r/RBloggers/~4/EI0sZJniuJw"></a></div>