This RMarkdown shows how I come up with my daily projections for MR Play. See here for how MR Play contests work.
# Load libraries
library(tidyverse)
library(stringi)
library(nbastatR)
# Load file that contains helper functions
source("TS_Functions.R")
First goal is to load daily stat projections from BasketballMonster (BBM), perform some cleaning, and compute their total points stat.
# Load BBM Projections from a csv file on the internet
bbmproj <- read_csv("https://basketballmonster.com/dailyprojections.aspx?exportcsv=TbRiHe8ctANfwMvqI6EetQdY4QsKbZvwhTJrUTJudBU=", show_col_types = FALSE)
# This below is for when I'm projecting for a specific day in advance
# setwd("/Users/billy/Downloads")
# bbmproj <- read_csv("Export_2022_03_15.csv", show_col_types = FALSE)
# Add column for the MR Play point system and sort by that column
# Combine First and Last Name columns into "Name"
# fixbballnames() is a cleaning function that makes sure names like Steph Curry and Stephen Curry match up
bbmproj2 <- bbmproj %>%
mutate(unboosted_projection = points + rebounds + 1.5*assists + 2*steals + 2*blocks, .before = value) %>%
arrange(desc(unboosted_projection)) %>%
mutate(Name = paste(first_name, last_name, sep = " "), .before = unboosted_projection) %>%
select(Name, Team = team, opponent, Injury = injury, unboosted_projection, Minutes = minutes, Points = points, Rebounds = rebounds, Assists = assists, Threes = threes,
Steals = steals, Blocks = blocks) %>%
fix_bball_names()
The last 10 day stats are needed for every player as that is how the boosts are calculated based upon being compared to.
# Load Last 10
setwd("/Users/billy/Downloads")
tenday <- read_csv("MRplayer10gameavg061522.csv", show_col_types = FALSE) #EDIT THIS LINE HERE
# Shorten the names of the stat columns
# Apply fixbballnames() name cleaning function
tenday2 <- tenday %>%
select(Name = YahooName, Points, Rebounds, Assists, Threes = ThreePointersMade, Steals, Blocks = BlockedShots, Games, Minutes, Started) %>%
mutate(Points = Points/Games,
Rebounds = Rebounds/Games,
Assists = Assists/Games,
Threes = Threes/Games,
Steals = Steals/Games,
Blocks = Blocks/Games) %>%
fix_bball_names() %>%
na.omit()
# Join Last 10 day stats with BBM Projections
df1 <- bbmproj2 %>%
left_join(tenday2, by = "Name", suffix = c(".proj", ".last10"))
# Filter to only include players with projections of 10 points or more
# Unselect irrelevant columns
df2 <- df1 %>%
select(-c(Games, Minutes.last10, Started))
# Test to see if any players have non-existent last-10-day stats, to be aware of them
df2[which(is.na(df2$Points.last10)),"Name"]
Load TopShot moment data from OTMNFT.com to determine which players have boosts in which stats.
# Load all TopShot moment data
topshotmoments <- read.csv("https://otmnftapi.com/nbatopshot/create_moments_csv", encoding = "Latin-1") %>% rename(Name = Player.Name)
# Convert European characters into English and perform the name cleaning function
topshotmoments <- topshotmoments %>%
mutate(Name = stri_trans_general(Name, 'latin-ascii')) %>%
fix_bball_names() %>%
I
# Function to convert TopShot moment stat categories to MR Play stat categories (e.g. "Layup" into "Points")
options <- simplify_moments(topshotmoments)
To determine the variability (standard devaition) of each player’s
statistical performance in each stat category, I’ll use their game logs
from the 2021-22 season. These are available through the package
nbastatR.
# Get game logs
Sys.setenv("VROOM_CONNECTION_SIZE" = 131072*2)
gamelog <- game_logs(seasons = 2022,
league = "NBA",
season_types = "Regular Season",
assign_to_environment = FALSE,
result_types = "player")
# Some cleaning to match the BBM Projections and Last 10 day stat data frames
gamelog <- gamelog %>%
rename(c(Name = namePlayer, Points = pts, Rebounds = treb, Assists = ast, Threes = fg3m, Steals = stl, Blocks = blk)) %>%
data.frame() %>%
fix_bball_names() %>%
I
options(digits = 2)
# Filter to only include players with projections of 10 points or more
tonight <- df2 %>% filter(unboosted_projection > 10)
# Apply the function "boosted_projection()" which calculates the expected value of an input stat for every NBA Player, given the MR Play boosts.
tonight$Points_boost = sapply(tonight$Name, boosted_projection, "Points")
tonight$Assists_boost = sapply(tonight$Name, boosted_projection, "Assists")
tonight$Threes_boost = sapply(tonight$Name, boosted_projection, "Threes")
tonight$Steals_boost = sapply(tonight$Name, boosted_projection, "Steals")
tonight$Blocks_boost = sapply(tonight$Name, boosted_projection, "Blocks")
# Any issues in this chunk of code have to do with name spelling inconsistencies, need to be added to fix_bball_names()
# Find the highest boost for each player and stor them into x
x<- NULL
for(i in 1:nrow(tonight)){
x[i] <- max(tonight[i,19:23], na.rm = TRUE)
}
# Add the highest boost into the main dataframe
tonight2 <- tonight %>%
mutate(best_boost = x, .before = Points_boost) %>%
mutate(boosted_projection = unboosted_projection + best_boost, .before = unboosted_projection) %>%
arrange(desc(boosted_projection))
tonight2 <- tonight2 %>%
relocate(best_boost:Blocks_boost, .before = Minutes.proj) %>%
mutate_if(is.numeric, round, 2)
# Publish the final dataframe to google sheets
library(googlesheets4)
tonight2 %>% sheet_write(ss = mrplay, sheet = "june-16")
Rearrange final output to look more like: Harden - assist - 65.7, Tatum - 3ptm - 60.1, Harden - 3ptm - 54.5, and …
Include the circulation counts and price to purchase each moment