library(tidyverse)
library(gt)

Getting the data

This data was extracted from the NBA’s Voting results for 2019 NBA All-Star Game starters using Thomas J. Leeper’s tabulizer package.1

I’m not gonna run through it here, but I used some tricks from a tutorial by Bruno Rodrigues to make getting the PDFs for each of the four categories (Eastern Conference Frontcourt, Eastern Conference Guards, Western Conference Frontcourt, Western Conference Guards) a bit easier.

######### Code in this chunk is not being run ##########

conference <- c("Eastern", "Western")
court <- c("Frontcourt", "Guard")

asg_combos <- crossing(conference, court) %>%
  mutate(filename = glue::glue("2019-{conference}-Conference-{court}-NBA-All-Star-Starter-Voting-Results"))

# create vector of filenames
filenames <- asg_combos$filename

# build urls
urls <- glue::glue("https://ak-static.cms.nba.com/wp-content/uploads/sites/46/2019/01/{filenames}.pdf")

# build PDF names
pdf_names <- glue::glue("{filenames}.pdf")

# download PDFs
walk2(urls, pdf_names, download.file, mode = "wb")

# use tabulizer to extract data from pages e.g.
out1 <- extract_tables(pdf_names[4], output = "data.frame", pages = 1)

# and get the contents into a data frame
df_p1 <- out1[[1]]

After a little bit of wrangling, I ended up with a single data frame, asg_votes (ASG stands for All-Star Game), which looks like this:

asg_votes <- read_csv(here::here("data", "ASG", "asg_votes.csv"))
glimpse(asg_votes)
## Observations: 491
## Variables: 16
## $ player             <chr> "Giannis Antetokounmpo", "Kawhi Leonard", "Jo…
## $ team_slug          <chr> "MIL", "TOR", "PHI", "BOS", "PHI", "DET", "TO…
## $ player_total_votes <dbl> 269, 189, 186, 19, 51, 50, 16, 11, 21, 17, 18…
## $ player_rank        <dbl> 1, 2, 3, 7, 4, 5, 10, 12, 6, 9, 8, 22, 12, 25…
## $ fan_total_votes    <dbl> 4375747, 3580531, 2783833, 1002885, 907775, 8…
## $ fan_rank           <dbl> 1, 2, 3, 4, 5, 6, 8, 7, 12, 13, 14, 10, 17, 1…
## $ media_total_votes  <dbl> 99, 99, 99, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, …
## $ media_rank         <dbl> 1, 1, 1, 4, 7, 7, 4, 7, 7, 4, 7, 7, 7, 7, 7, …
## $ weighted_score     <dbl> 1.00, 1.75, 2.50, 4.75, 5.25, 6.00, 7.50, 8.2…
## $ conference         <chr> "eastern", "eastern", "eastern", "eastern", "…
## $ court              <chr> "frontcourt", "frontcourt", "frontcourt", "fr…
## $ conf_court         <chr> "eastern frontcourt", "eastern frontcourt", "…
## $ player_name_team   <chr> "Antetokounmpo, Giannis -- MIL", "Leonard, Ka…
## $ player_name        <chr> "Antetokounmpo, Giannis", "Leonard, Kawhi", "…
## $ last_name          <chr> "Antetokounmpo", "Leonard", "Embiid", "Tatum"…
## $ first_name         <chr> "Giannis", "Kawhi", "Joel", "Jayson", "Jimmy"…

That player_name_team variable comes from the original input from the PDF. Using stringr to extract the last three characters for the team slugs, and everything but the last eight characters for the player names worked in most cases.

# get team slug
stringr::str_sub(x, start = -3)
# get player name
stringr::str_sub(x, end = -8)

But, there were a few outliers where players have changed teams during the season (e.g. see Kenneth Faried and Justin Holiday’s entries below), or aren’t currently with a team, so I wanted to keep the original data around just in case.

Atypical data in Eastern Conference Frontcourt voting results for 2019 NBA All-Star Game

Atypical data in Eastern Conference Frontcourt voting results for 2019 NBA All-Star Game

NBA All-Star Voting 2019 Results

Now let’s recreate the top 10 tables they have in the official release, NBA All-Star 2019 starters, captains revealed, using the gt package by Rich Iannone.

Western Conference Frontcourt

asg_votes %>%
  filter(conf_court == "western frontcourt") %>%
  arrange(weighted_score) %>%
  mutate(rank = row_number()) %>%
  filter(rank <= 10) %>%
  select(rank, player, team_slug, fan_rank, player_rank, media_rank, weighted_score) %>%
  gt() %>%
  tab_header(
    title = md("**Western Conference Frontcourt**"),
    subtitle = glue::glue("NBA All-Star Voting 2019 Results")
  ) %>%
  cols_label(rank = md("**Rank**"),
             player = md("**Player Name**"),
             team_slug = md("**Team**"),
             fan_rank = md("**Fan Rank**"),
             player_rank = md("**Player Rank**"),
             media_rank = md("**Media Rank**"),
             weighted_score = md("**Weighted Score**")) %>%
  tab_source_note(md("source: [nba.com](http://www.nba.com/article/2019/01/24/2019-nba-all-star-starters-revealed-official-release)")) %>%
    tab_footnote(
    footnote = "Voted to start",
    locations = cells_data(
      columns = vars(player),
      rows = 1:3)
  ) %>%
    tab_footnote(
    footnote = "Team captain",
    locations = cells_data(
      columns = vars(player),
      rows = 1)
  ) %>%
    tab_footnote(
    footnote = "Tiebreaker for starting spot is fan rank",
    locations = cells_data(
      columns = vars(weighted_score),
      rows = 3:4)
  ) %>%
  tab_options(footnote.glyph = c("*, †, ‡"))
Western Conference Frontcourt
NBA All-Star Voting 2019 Results
Rank Player Name Team Fan Rank Player Rank Media Rank Weighted Score
1 LeBron James*, † LAL 1 1 1 1.00
2 Kevin Durant* GSW 3 2 2 2.50
3 Paul George* OKC 4 4 4 4.00
4 Anthony Davis NOP 5 3 3 4.00
5 Luka Doncic DAL 2 8 6 4.50
6 Nikola Jokic DEN 7 5 5 6.00
7 Steven Adams OKC 6 7 8 6.75
8 Draymond Green GSW 9 10 8 9.00
9 Karl-Anthony Towns MIN 11 10 8 10.00
10 LaMarcus Aldridge SAS 13 6 8 10.00
source: nba.com
* Voted to start
Team captain
Tiebreaker for starting spot is fan rank

Western Conference Backcourt

Western Conference Backcourt
NBA All-Star Voting 2019 Results
Rank Player Name Team Fan Rank Player Rank Media Rank Weighted Score
1 Stephen Curry* GSW 1 1 2 1.25
2 James Harden* HOU 3 2 1 2.25
3 Derrick Rose MIN 2 4 6 3.50
4 Russell Westbrook OKC 4 3 3 3.50
5 Damian Lillard POR 6 5 4 5.25
6 Klay Thompson GSW 5 11 4 6.25
7 DeMar DeRozan SAS 7 8 6 7.00
8 Devin Booker PHX 10 6 6 8.00
9 Lonzo Ball LAL 8 14 6 9.00
10 Chris Paul HOU 9 14 6 9.50
source: nba.com
* Voted to start

Eastern Conference Frontcourt

Eastern Conference Frontcourt
NBA All-Star Voting 2019 Results
Rank Player Name Team Fan Rank Player Rank Media Rank Weighted Score
1 Giannis Antetokounmpo*, † MIL 1 1 1 1.00
2 Kawhi Leonard* TOR 2 2 1 1.75
3 Joel Embiid* PHI 3 3 1 2.50
4 Jayson Tatum BOS 4 7 4 4.75
5 Jimmy Butler PHI 5 4 7 5.25
6 Blake Griffin DET 6 5 7 6.00
7 Pascal Siakam TOR 8 10 4 7.50
8 Vince Carter ATL 7 12 7 8.25
9 Andre Drummond DET 12 6 7 9.25
10 Nikola Vucevic ORL 13 9 4 9.75
source: nba.com
* Voted to start
Team captain

Eastern Conference Backcourt

Eastern Conference Backcourt
NBA All-Star Voting 2019 Results
Rank Player Name Team Fan Rank Player Rank Media Rank Weighted Score
1 Kyrie Irving* BOS 1 1 1 1.0
2 Kemba Walker* CHA 3 2 2 2.5
3 Dwyane Wade MIA 2 6 6 4.0
4 Ben Simmons PHI 4 5 3 4.0
5 Victor Oladipo IND 5 4 4 4.5
6 Kyle Lowry TOR 6 7 7 6.5
7 Bradley Beal WAS 10 3 5 7.0
8 Zach LaVine CHI 7 8 8 7.5
9 D'Angelo Russell BKN 11 10 8 10.0
10 Eric Bledsoe MIL 16 8 8 12.0
source: nba.com
* Voted to start.

  1. Yes, they are barbarians and insist on turning perfectly machine-readable excel sheets into PDFs for reasons unknown.