HyannisHarborHawks commited on
Commit
fa8d02f
·
verified ·
1 Parent(s): 59dca3d

Update app.R

Browse files
Files changed (1) hide show
  1. app.R +101 -0
app.R CHANGED
@@ -152,6 +152,9 @@ team_leagues <- download_private_csv("HyannisHarborHawksCCBL/CleanDataObjects",
152
  college_guts <- download_private_csv("HyannisHarborHawksCCBL/CleanDataObjects", "college_GUTS.csv")
153
  college_join <- download_private_csv("HyannisHarborHawksCCBL/CleanDataObjects", "college_join.csv")
154
 
 
 
 
155
  #Team logo
156
  logo_b64 <- base64enc::base64encode("HHLogo.png")
157
  logo_uri <- paste0("data:image/png;base64,", logo_b64)
@@ -160,6 +163,102 @@ logo_uri <- paste0("data:image/png;base64,", logo_b64)
160
  #Clean data
161
  # ============================================================
162
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
  #Function that predicts stuffplus
164
  predict_stuffplus <- function(data) {
165
 
@@ -282,6 +381,8 @@ clean_college_data <- function(data, teams = NA) {
282
  TaggedPitchType == "Undefined" ~ "Other",
283
  T ~ TaggedPitchType
284
  ))
 
 
285
 
286
  #Main aggregations
287
  data <- data %>%
 
152
  college_guts <- download_private_csv("HyannisHarborHawksCCBL/CleanDataObjects", "college_GUTS.csv")
153
  college_join <- download_private_csv("HyannisHarborHawksCCBL/CleanDataObjects", "college_join.csv")
154
 
155
+ #Reference arsenal data (only pitches thrown over 5% for retagging)
156
+ pitcher_arsenals_over_5perc <- download_private_csv("HyannisHarborHawksCCBL/CleanDataObjects", "pitcher_arsenals_over_5perc.csv")
157
+
158
  #Team logo
159
  logo_b64 <- base64enc::base64encode("HHLogo.png")
160
  logo_uri <- paste0("data:image/png;base64,", logo_b64)
 
163
  #Clean data
164
  # ============================================================
165
 
166
+ #Function that retags pitches into a column of a Trackman dataset
167
+ retag_pitches <- function(data) {
168
+
169
+ #Uses create_pitcher_arsenals function to get arsenals from reference set (college season)
170
+ arsenal_percentages <- pitcher_arsenals_over_5perc %>%
171
+ mutate(in_reference = TRUE)
172
+
173
+ # get row ID for joins later
174
+ data <- data %>% mutate(row_id = row_number())
175
+
176
+ #aggregation that prepares data for prediction (removes NAs, creates features, flips HorzBreak and RelSide)
177
+ predict_data <- data %>%
178
+ filter(
179
+ !Pitcher %in% unique(tagged_sample$Pitcher),
180
+ !TaggedPitchType %in% c("Other", "Undefined", "FastBall", "Knuckleball"),
181
+ !is.na(TaggedPitchType), !is.na(RelSpeed),
182
+ !is.na(InducedVertBreak), !is.na(Extension)
183
+ ) %>%
184
+ mutate(
185
+ max_velo_diff = max(RelSpeed, na.rm = TRUE) - RelSpeed,
186
+ max_vert_diff = InducedVertBreak[which.max(RelSpeed)] - InducedVertBreak,
187
+ max_ext_diff = Extension[which.max(RelSpeed)] - Extension,
188
+ .by = c(GameUID, Pitcher)
189
+ ) %>%
190
+ mutate(
191
+ RelSide = case_when(
192
+ PitcherThrows == "Right" ~ RelSide,
193
+ PitcherThrows == "Left" ~ -RelSide,
194
+ PitcherThrows %in% c("Both", "Undefined") & RelSide > 0 ~ RelSide,
195
+ PitcherThrows %in% c("Both", "Undefined") & RelSide < 0 ~ -RelSide),
196
+ HorzBreak = case_when(
197
+ PitcherThrows == "Right" ~ HorzBreak,
198
+ PitcherThrows == "Left" ~ -HorzBreak,
199
+ PitcherThrows %in% c("Both", "Undefined") & HorzBreak > 0 ~ HorzBreak,
200
+ PitcherThrows %in% c("Both", "Undefined") & HorzBreak < 0 ~ -HorzBreak)
201
+ )
202
+
203
+ #Predcted probabilities from model
204
+ probs <- predict(final_fit, predict_data, type = "prob")
205
+ pred_col_names <- names(probs)
206
+
207
+ #Get row_id for join
208
+ probs$row_id <- predict_data$row_id
209
+
210
+ #Join over probabilities
211
+ data <- data %>%
212
+ left_join(arsenal_percentages, by = "Pitcher") %>%
213
+ left_join(probs, by = "row_id") %>%
214
+ select(-row_id)
215
+
216
+ #Determine if pitcher has reference data (pitched in college season)
217
+ has_arsenal <- !is.na(data$in_reference)
218
+
219
+ # mask only pitchers who are in the reference, everyone else predicts normally, meaning a pitcher not in the reference has no
220
+ #arsenal constraint and is just given the model prediction. everyone else moves to the next steps:
221
+ pitch_to_perc <- c(
222
+ .pred_Fastball = "perc_FF", .pred_Cutter = "perc_CT",
223
+ .pred_Sinker = "perc_SI", .pred_Slider = "perc_SL",
224
+ .pred_Sweeper = "perc_SW", .pred_Curveball = "perc_CU",
225
+ .pred_Changeup = "perc_CH", .pred_Splitter = "perc_SP"
226
+ )
227
+ for (pc in intersect(names(pitch_to_perc), names(data))) {
228
+ ac <- pitch_to_perc[[pc]]
229
+ mult <- ifelse(has_arsenal, as.numeric(coalesce(data[[ac]], 0) > 0), 1)
230
+ data[[pc]] <- data[[pc]] * mult
231
+ }
232
+
233
+ #Build a matrix of the (now masked) class probabilities
234
+ prob_mat <- as.matrix(data[pred_col_names])
235
+
236
+ #Flag rows that actually got scored, unscored rows stay all-NA and are skipped
237
+ predicted <- rowSums(!is.na(prob_mat)) > 0
238
+
239
+ #Start everyone as NA, only scored rows get a tag
240
+ pt <- rep(NA_character_, nrow(data))
241
+
242
+ #Pull just the scored rows, zero out NAs so max.col can run
243
+ m <- prob_mat[predicted, , drop = FALSE]
244
+ m[is.na(m)] <- 0
245
+
246
+ #Pick the highest surviving probability per row as the predicted pitch
247
+ pt[predicted] <- pred_col_names[max.col(m, ties.method = "first")]
248
+
249
+ #Strip the ".pred_" prefix to get a clean pitch type, drop the helper column
250
+ data$TaggedPitchType <- sub("^\\.pred_", "", pt)
251
+ data %>% select(-in_reference)
252
+
253
+ #make all splitters change ups
254
+ data <- data %>%
255
+ mutate(TaggedPitchType = ifelse(TaggedPitchType == "Splitter", "Changeup", TaggedPitchType))
256
+
257
+ return(data)
258
+
259
+ }
260
+
261
+
262
  #Function that predicts stuffplus
263
  predict_stuffplus <- function(data) {
264
 
 
381
  TaggedPitchType == "Undefined" ~ "Other",
382
  T ~ TaggedPitchType
383
  ))
384
+
385
+ data <- retag_pitches(data)
386
 
387
  #Main aggregations
388
  data <- data %>%