top of page

Playing Fantasy Basketball Using R and Shiny

  • Writer: Andy Chen
    Andy Chen
  • Jan 30, 2020
  • 5 min read

Updated: Sep 29, 2020

I've been one of the most loyal NBA fans among my peers ever since the Lakers eviscerated Orlando Magic in 08-09, and as a long-time NBA fanatic, Kobe's devastating death left me in shock and disbelief for days, especially because of how and when it happened. Having said that, I believe that Kobe and Gigi would surely encourage us to try to move on, converting the pain and grief into our motivation. Hence, to honor the legend, I decided to carry out something that I had planned to do for quite a while — an NBA fantasy score tracker.

Why a fantasy score tracker, you might ask. Well, ever since I started watching NBA, aside from admiring the spectacular highlights, I found myself crazy obsessed with the box scores after every game, unknowingly memorizing how many points Kobe scored again, LeBron's insane triple-double stat lines, Chris Paul's wizardry with his assists, the list goes on and on. Thus, fantasy basketball is just the thing for an NBA lover and stat geek like me. However, online fantasy leagues are a bit too troublesome and time-consuming for my liking, so I've always wanted to find an alternative way to build a fantasy team of my own. As I picked up the shiny package in R with the DataCamp Shiny track, I found out how easy it is to build a data-tracking dashboard using shiny, and the rest is history.


Dashboard Preparations

I wanted my dashboard to have 4 main features:

1. Head-to-head comparisons between players

2. A team-building mechanism

3. A search engine for players' career stats

4. A fantasy score calculator

Furthermore, in order to make it easier for me to get the project off the ground, I decided to just calculate players' career fantasy score averages, instead of tracking stats on a daily basis.


I'll mainly be utilizing the powerful shiny/shinydashboard and tidyverse packages in R, including rvest for web scraping my stats from the leading basketball statistics site Basketball Reference, and topping it off by deploying the application on the web with shinyapps.io.


For starters, we'll need to write a function to obtain real time player stats. After some examination of the site's layout, I decided to start by extracting the starting letter of the inputted players' initials to search for every players' stats page. One thing to take notice though, is that active players are displayed in bold text on this site, so we need to slightly alter the xpath to get the correct link.

Once we get the link to the players' page, we can navigate through players' attributes with ease. In this case, I'll be collecting their career stats, summary stats, and images displayed on the site. This can be easily achieved using rvest and xpath, considering that the site's layout is quite simple. Filtering out our desired content, on the contrary, could be a bit tricky. This is where the stringr package and regex come into play. With regex, we can determine the exact content of our choice from strings. While regex can be intimidating, it proves to be a powerful tool when dealing with strings, so I'm still trying to become more comfortable with it . I also wrote a simple function to define the fantasy score formula, which equals to PTS + 1.2 * TRB + 1.5 * AST + 3 * STL + 3 * BLK - TOV according to the league.

Constructing the Dashboard

With these formulas in place, we can finally start designing our dashboard! Shiny apps have two components, a user interface object and a server function, that are passed as arguments to the "shinyApp" function. Simply put, we can design the layout in the UI object, and determine the content in the server function. To keep this article shorter, I'll mostly be covering the UI of my dashboard, only briefly going through some of the key elements in the server. If you're interested, the complete code can be found here.


For the UI of the app, I chose a sidebar/body layout. The sidebar is written with three Shiny functions — "textInput", which takes the users' inputted text; "selectInput", giving users a set of choices to select from; and "actionButton", which is handy when you wish the content to be updated and displayed dynamically. We can manually change the design of each of these elements, and if you're not satisfied with some of the details, it is also possible to edit them using CSS. This really comes to show how interactive and flexible Shiny is.

The body of the dashboard is my entrée, which can be split into two parts, i.e., two "tabPanel" tabs. The first tab, is the stat searcher. It consists of three main elements — the first inputted players' career stats, a graph for the head-to-head comparison between the two players, and two value boxes to show their fantasy scores. The datatable format can be generated with the DT package, creating an effective table that looks pretty good at the same time. As for the graph, I used a combination of ggplot2 and plotly to create an interactive plot, comparing the two players over the course of their careers. Users can also select different attributes to plot on the graph, just to add a bit more functionality to the chart. The video below is a small demonstration.

The second section of the body, is the fantasy team builder. As shown in the video, we can type in the players of our choice, then calculate the total fantasy score of our fantasy team. It isn't much, but if you're looking to have a rough idea of how the players are doing so far in their careers, I'd say it's quite serviceable.

As for the server function, I excerpted just some notable parts to demonstrate how the code works, including the basic building blocks for the datatable, the ggplotly graph, and the players' images. I also want to talk about two important functions in constructing the server in Shiny apps — "reactive" and "isolate". Elements in the server function more often than not depend on some sort of reactive value, and in order to reference these elements later, we'll need to wrap them in a "reactive" function. The "isolate" function, on the other hand, is usually used alongside action buttons to ensure the preliminary conditions are met before our elements are rendered. Once you get the hang of the "reactive", "isolate", and "render" functions, scripting the server should be no problem.

The last step, is to put it all together with the "shinyApp" function, and present your app for the world to see on shinyapps.io, where deploying Shiny apps on the web couldn't get any easier. All you need is a shinyapps.io account, the rsconnect package, and a simple command. Tutorials can also be found here. Deploying apps on the web makes it much more easier to share your work with others, and makes it look extra smooth and impressive (which was definitely not my main concern).


This is just a simple prototype of my fantasy score tracker, and there are still some bugs yet to be fixed, but I'll definitely be adding more features to it as I continue to brush up my skills in R. Once again, feel free to check out the app deployed on shinyapps.io here, and the complete code over here if you're also a mega NBA fan like me!

Comentarios


© 2020 by ANDY CHEN

bottom of page