knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.path = "man/figures/README-",
  out.width = "100%"
)

nbaWinLossExplorer

The nbaWinLossExplorer shiny app was created as part of STA 2453 to demonstrate building shiny applications for productions. The application itself is used to explore expected win/loss records for NBA teams.

The idea came from the weird and awful 2020-2021 Toronto Raptors season. The raptors finished the season with 27 wins and 45 losses, but for most of the season has a positive plus/minus (i.e. they scored more points than their opponents). A natural question arises: how does a team with a losing record but a positive plus/minus perform?

The application makes use of every game played in the NBA since 1947. A user can select a number of wins and losse, as well as a plus/minus differential (within a tolerance), and see the final season outcomes for every team who matched those inputs.

For example, let's look at one example. Let's look at all teams that started their season with 5 wins and 5 loses, with a plus minus between -10 and + 10. We are going to make use of the data that loads with the package (nba_season_data)

library(dplyr)
library(ggplot2)
library(nbastatR)
library(nbaWinLossExplorer)

 acceptable_records <- nba_season_data %>%
            mutate(contains_record = (wins == 5) &
                       (losses == 5) &
                       (plus_minus_post >= -10 ) &
                       (plus_minus_post <= 10)) %>%
            group_by(name_team, year_season) %>%
            arrange(date_game) %>%
            mutate(keep = max(contains_record)) %>%
            filter(keep > 0) %>%
            ungroup()

Below we can plot all of the matching records.

example_season_plot <- acceptable_records %>%
            ggplot(aes(number_game_team_season, wins, color = id)) +
            geom_line() +
            labs(x = "Game number of season",
                 y = "Number of wins")  +
            theme_minimal()+
            theme(legend.position='none') +
            theme(axis.text.x = element_text(colour = "#006bb8"),
                  axis.text.y = element_text(colour = "#006bb8"),
                  axis.title.x = element_text(colour = "#032f4f"),
                  axis.title.y = element_text(colour = "#032f4f"))

example_season_plot

We can see the lines cross where every team was 5-5. Now we can calculate some sample statistics.

season_summary <- acceptable_records %>% 
  group_by(id) %>% 
  slice(1) %>% 
  ungroup()

# how many teams match the requirements
nrow(season_summary)

# what proportion make the playoffs
sum(season_summary$made_playoffs)/nrow(season_summary)

# distribution of wins and losses at the end of the season
summary(season_summary$final_wins)
summary(season_summary$final_losses)

We can see that r nrow(season_summary) teams match these requirements, with r paste0(100*round(sum(season_summary$made_playoffs)/nrow(season_summary), 3), "%") making the playoffs. The median number of wins is r median(season_summary$final_wins) (IQR r quantile(season_summary$final_wins, .25)-r quantile(season_summary$final_wins, .75)) and median number of losses of r median(season_summary$final_losses) (IQR r quantile(season_summary$final_losses, .25)-r quantile(season_summary$final_losses, .75)). So on average, teams finish with roughly the same number of wins and losses.

For more detail see the package vignette.

Installation

The development version from GitHub with:

# install.packages("devtools")
devtools::install_github("murrayjw/nbaWinLossExplorer")

To run the app

# install.packages("devtools")
nbaWinLossExplorer::run_app()


murrayjw/nbaWinLossExplorer documentation built on Dec. 21, 2021, 11:02 p.m.