reactable

24/3/2022 4-minute read

Background

I wanted to try reactable, and NBA playoffs start in April.

Set Up

Handy dandy options,

# Global Options 
knitr::opts_chunk$set(error=FALSE,
                      message= FALSE,
                      warning=FALSE)

and libraries.

# Load Libraries 
library(rvest) 
library(tidyverse) 
library(reactable)

Harvest the data with rvest

I could easily pull the CSV’s off Basketball Reference, but I might want to come back and adjust this post later. It would be pretty tedious to save those data sets again, so instead I am using the package rvest to harvest the data directly off the web page. For this table I am pulling the top team in the west, which is the Phoenix Suns and the top teams in the east, which is the Miami Heat.

# Add team name and team slug
suns <- "Phoenix Suns"
suns_slug <- "PHO"

heat <- "Miami Heat"
heat_slug <- "MIA"

# define player page URL
suns_url <- paste0("https://www.basketball-reference.com/teams/",suns_slug,"/2022.html")

heat_url <- paste0("https://www.basketball-reference.com/teams/",heat_slug,"/2022.html")

If you check either of these teams Basketball Reference page you will see there is a lot of data and statistics available. Since I really just want to try reactable, lets just look at the Total stats.

# Read total stats
suns_ttl_stat <- suns_url %>%
  read_html %>%
  html_node("#totals") %>% 
  html_table()

heat_ttl_stat <- heat_url %>%
  read_html %>%
  html_node("#totals") %>% 
  html_table()

Tidy

To tidy this data there are four main things I am doing:

  • add “Name” to the column with players names

  • add column with team name (as to be able to sort by team)

  • merge Suns and Heats tables

  • Remove NA rows and extra columns

# Rename Column 2 Name 
names(suns_ttl_stat)[2] <- "Name"
names(heat_ttl_stat)[2] <- "Name"

# Add Column with Team Name
suns_ttl_stat$Team <- suns
heat_ttl_stat$Team <- heat

# Merge stats tables
total_stats <- full_join(suns_ttl_stat, heat_ttl_stat) 

# Remove NA rows and extra column data 
total_stats <- total_stats %>% 
  filter(!is.na(Rk)) %>%
  select(Team, Name, Rk, Age, G, MP, PTS, FG, `3P`, `2P`, FT, AST, STL, BLK, TOV, PF)

# View Data
head(total_stats)
## # A tibble: 6 × 16
##   Team   Name     Rk   Age     G    MP   PTS    FG  `3P`  `2P`    FT   AST   STL
##   <chr>  <chr> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int>
## 1 Phoen… Mika…     1    25    74  2621  1056   415   110   305   116   172    88
## 2 Phoen… Devi…     2    25    63  2168  1659   602   167   435   288   314    76
## 3 Phoen… Chri…     3    36    59  1946   883   331    61   270   160   632   109
## 4 Phoen… Jae …     4    31    62  1745   592   204   117    87    67   112    85
## 5 Phoen… Came…     5    25    60  1579   770   261   159   102    89    89    50
## 6 Phoen… Dean…     6    23    53  1560   917   407     6   401    97    75    38
## # … with 3 more variables: BLK <int>, TOV <int>, PF <int>

Reactable

There were five main things I wanted from this table:

  • groupBy = Team

  • remane columns

  • bordered

  • highlight

  • searchable

  • minRows = number of teams showing (which is 2)

reactable(
  total_stats,
  groupBy = "Team",
  columns = list(
    Rk = colDef(name = "Rank"),
    G = colDef(name = "Games"),
    MP = colDef(name = "Minutes Played"),
    FG = colDef(name = "Field Goals"),
    `3P` = colDef(name = "3 Point Goals"),
    `2P` = colDef(name = "2 Point Goals"),
    FT = colDef(name = "Free Throws"),
    AST = colDef(name = "Assists"),
    STL = colDef(name = "Steals"),
    BLK = colDef(name = "Blocks"),
    PTS = colDef(name = "Points"),
    TOV = colDef(name = "Turnovers"),
    PF = colDef(name = "Personal Fouls")
  ),
  bordered = TRUE,
  highlight = TRUE,
  filterable = TRUE,
  searchable = TRUE,
  minRows = 2
  )

Future Updates

  • Create a question to look at

  • Add Functions to look at more teams / reduce code

  • Add Graphs or other visuals

Clean Up Reactable:

  • Add logos

  • Add Graphs

  • Narrow Data and Compute Statistics

  • Add more teams