TimStats commited on
Commit
80187e7
·
verified ·
1 Parent(s): 70a2d19

Update app.R

Browse files
Files changed (1) hide show
  1. app.R +478 -478
app.R CHANGED
@@ -1,478 +1,478 @@
1
- library(shiny)
2
- library(gt)
3
- library(dplyr)
4
- library(shinyjs)
5
- library(shinyauthr)
6
- library(gtExtras)
7
- library(bslib)
8
-
9
- Bean <- read.csv('Beam.csv')
10
-
11
- test <- Beam %>%
12
- select(Date,PitchofPA,Pitcher,PitcherId,PitcherThrows,PitcherTeam,Batter,BatterId,
13
- BatterSide,BatterTeam,Inning,`Top/Bottom`,Outs,Balls,Strikes,TaggedPitchType,
14
- AutoPitchType,PitchCall,TaggedHitType,KorBB,PlayResult,OutsOnPlay,RunsScored,
15
- RelSpeed,VertRelAngle,HorzRelAngle,SpinRate,SpinAxis,Tilt,RelHeight,RelSide,
16
- Extension,InducedVertBreak,HorzBreak,PlateLocHeight,PlateLocSide,VertApprAngle,
17
- HorzApprAngle,ExitSpeed,Angle,Direction,Distance,pfxx,pfxz,x0,z0,vx0,vy0,vz0,
18
- ax0,ay0,az0,Level,League,ContactPositionX,ContactPositionY,ContactPositionZ,
19
- SpinAxis3dTransverseAngle,SpinAxis3dLongitudinalAngle,SpinAxis3dTilt,
20
- SpinAxis3dSpinEfficiency,SpinAxis3dSeamOrientationRotationX,
21
- SpinAxis3dSeamOrientationRotationY,SpinAxis3dSeamOrientationRotationZ)
22
- test <- test %>%
23
- mutate("Hit" = case_when(PlayResult %in% c("Single","Double","Triple","HomeRun") ~ TRUE,TRUE ~ FALSE),
24
- "CallStrike" = case_when(PitchCall %in% c("StrikeCalled") ~ TRUE, TRUE ~ FALSE),
25
- "Whiff" = case_when(PitchCall %in% c("StrikeSwinging") ~ TRUE, TRUE ~ FALSE),
26
- "CSW" = CallStrike + Whiff,
27
- "Contact" = case_when(PitchCall %in% c("FoulBall","FouBallNotFieldable","InPlay") ~ TRUE, TRUE ~ FALSE),
28
- "GB" = case_when(TaggedHitType %in% c('GroundBall') ~ TRUE, TRUE ~ FALSE),
29
- "LD" = case_when(TaggedHitType %in% c('LineDrive') ~ TRUE, TRUE ~ FALSE),
30
- "FB" = case_when(TaggedHitType %in% c ("FlyBall") ~ TRUE, TRUE ~ FALSE),
31
- "PopU" = case_when(TaggedHitType %in% c ("Popup") ~ TRUE, TRUE ~ FALSE),
32
- "Swing" = Whiff + Contact,
33
- "BBE" = GB + LD + FB + PopU,
34
- "HardHit" = ifelse(ExitSpeed >= 95,TRUE,FALSE),
35
- "Ball" = case_when(PitchCall %in% c("BallCalled","BallinDirt") ~ TRUE, TRUE ~ FALSE),
36
- "Single" = case_when(PlayResult %in% c("Single") ~ TRUE, TRUE ~ FALSE),
37
- "Double" = case_when(PlayResult %in% c("Double") ~ TRUE, TRUE ~ FALSE),
38
- "Triple" = case_when(PlayResult %in% c("Triple") ~ TRUE, TRUE ~ FALSE),
39
- "HR" = case_when(PlayResult %in% c("HomeRun") ~ TRUE, TRUE ~ FALSE),
40
- "Sac" = case_when(PlayResult %in% c("Sacrifice") ~ TRUE, TRUE ~ FALSE),
41
- "HBP" = case_when(PitchCall %in% c("HitByPitch") ~ TRUE, TRUE ~ FALSE),
42
- "Error" = case_when(PlayResult %in% c("Error") ~ TRUE, TRUE ~ FALSE),
43
- "FC"= case_when(PlayResult %in% c("FieldersChoice") ~ TRUE, TRUE ~ FALSE),
44
- "Out" = case_when(PlayResult %in% c ("Out") ~ TRUE, TRUE ~ FALSE),
45
- "BIP" = Single + Double + Triple + HR + Sac + Error + Out + FC,
46
- "Count" = paste0(Balls,"-",Strikes),
47
- "Strikeout" = ifelse(KorBB == "Strikeout",TRUE,FALSE),
48
- "Walk" = ifelse(KorBB == "Walk",TRUE,FALSE),
49
- "Zone" = case_when(between(PlateLocSide,-.825,.825) & between(PlateLocHeight,1.45,3.45) ~ TRUE, TRUE ~ FALSE),
50
- "AB" = Strikeout + BIP - Sac,
51
- "PA" = Strikeout + BIP + Walk + HBP
52
- )
53
-
54
-
55
- gt_theme_tim <- function(gt_object,...) {
56
-
57
- stopifnot(`'gt_object' must be a 'gt_tbl', have you accidentally passed raw data?` = "gt_tbl" %in%
58
- class(gt_object))
59
-
60
- table_id <- subset(gt_object[['_options']], parameter == 'table_id')$value[[1]]
61
-
62
- if (is.na(table_id)) {
63
- table_id <- gt::random_id()
64
- opt_position <- which("table_id" %in% gt_object[["_options"]][["parameter"]])[[1]]
65
- gt_object[["_options"]][["value"]][[opt_position]] <- table_id
66
- }
67
-
68
- gt_object %>%
69
- # cell body
70
- gt::tab_style(
71
- locations = gt::cells_body(),
72
- style = gt::cell_text(font = "Arial", size = px(14))
73
- ) %>%
74
- # col. headers
75
- gt::tab_style(
76
- locations = gt::cells_column_labels(),
77
- style = gt::cell_text(weight = 'bold', font = "Arial", size = px(14))
78
- ) %>%
79
- # group rows
80
- gt::tab_style(
81
- locations = gt::cells_row_groups(),
82
- style = list(
83
- gt::cell_text(font = "Arial", weight = 650, size = px(14), color = "#FFFDF5"),
84
- gt::cell_fill(color = "#000000")
85
- )
86
- ) %>%
87
- # footnote
88
- gt::tab_style(
89
- locations = gt::cells_footnotes(),
90
- style = gt::cell_text(font = "Arial", size = px(12))
91
- ) %>%
92
- # title
93
- gt::tab_style(
94
- locations = gt::cells_title('title'),
95
- style = gt::cell_text(weight = 'bold', font = "Arial", size = px(18))
96
- ) %>%
97
- # subtitle
98
- gt::tab_style(
99
- locations = gt::cells_title('subtitle'),
100
- style = gt::cell_text(font = "Arial", size = px(14))
101
- ) %>%
102
- # caption
103
- gt::tab_style(
104
- locations = gt::cells_source_notes(),
105
- style = gt::cell_text(font = "Arial", size = px(12))
106
- ) %>%
107
- # spanner
108
- gt::tab_style(
109
- locations = gt::cells_column_spanners(),
110
- style = gt::cell_text(font = "Arial", weight = 650, size = px(8))
111
- ) %>%
112
- gt::tab_options(
113
- data_row.padding = 1,
114
- table_body.hlines.color = "transparent",
115
- column_labels.border.top.color = 'black',
116
- column_labels.border.top.width = px(1),
117
- column_labels.border.bottom.style = 'none',
118
- #column_labels.background.color = "orange",
119
- row_group.border.top.style = "none",
120
- row_group.border.top.color = "black",
121
- row_group.border.bottom.width = px(1),
122
- row_group.border.bottom.color = "black",
123
- row_group.border.bottom.style = 'solid',
124
- row_group.padding = px(1.5),
125
- heading.align = 'center',
126
- heading.border.bottom.style = "none",
127
- table_body.border.top.style = "none",
128
- table_body.border.bottom.color = "white",
129
- table.border.bottom.style = 'none',
130
- table.border.top.style = 'none',
131
- source_notes.border.lr.style = "none",
132
- ...
133
- ) %>%
134
- gt::opt_row_striping()
135
- }
136
-
137
- user_base <- tibble::tibble(
138
- user = c("TrentR", "user2"),
139
- password = sapply(c("Caprisun", "pass2"), sodium::password_store),
140
- permissions = c("admin", "standard"),
141
- name = c("User One", "User Two")
142
- )
143
-
144
- # Define UI for application that draws a histogram
145
- ui <- fluidPage(
146
- div(class = "pull-right", shinyauthr::logoutUI(id = "logout")),
147
-
148
- # login section
149
- shinyauthr::loginUI(id = "login"),
150
-
151
- div(
152
- id = "bar",
153
- # Application title
154
- titlePanel("College Pitcher"),
155
-
156
- # Sidebar layout
157
- sidebarLayout(
158
- sidebarPanel(
159
- selectInput("player",
160
- "Select Player",
161
- choices = unique(test$Pitcher)),
162
- width = 3
163
- ),
164
-
165
- mainPanel(
166
- tabsetPanel(
167
- tabPanel("Splits",
168
- gt_output("CountFilter"),
169
- gt_output("PitchFilter"),
170
- gt_output("PitchSideFilter"),
171
- gt_output("InningFilter"),
172
- gt_output("SideFilter")
173
- )
174
- ),
175
- width = 9
176
- )
177
- )
178
- ) %>% shinyjs::hidden()
179
- )
180
-
181
- # Define server logic required to draw a histogram
182
- server <- function(input, output) {
183
-
184
- credentials <- shinyauthr::loginServer(
185
- id = "login",
186
- data = user_base,
187
- user_col = user,
188
- pwd_col = password,
189
- sodium_hashed = TRUE,
190
- log_out = reactive(logout_init())
191
- )
192
-
193
- # Logout to hide
194
- logout_init <- shinyauthr::logoutServer(
195
- id = "logout",
196
- active = reactive(credentials()$user_auth)
197
- )
198
-
199
- observe({
200
- req(credentials()$user_auth)
201
- shinyjs::show(id = "bar")
202
- })
203
-
204
- output$CountFilter <- render_gt({
205
- test <- test %>% filter(Pitcher == input$player) %>% group_by(Count) %>%
206
- summarise(
207
- Pitches = n(),
208
- #BBE = sum(BBE,na.rm = TRUE),
209
- "Whiff%" = mean(Whiff,na.rm = TRUE),
210
- "CSW%" = mean(CSW,na.rm = TRUE),
211
- "Zone%" = mean(Zone,na.rm = TRUE),
212
- "ZCon%" = mean(Contact[Zone == TRUE & Swing == TRUE],na.rm = TRUE),
213
- "ZSwing%" = mean(Swing[Zone == TRUE],na.rm = TRUE),
214
- "OCon%" = mean(Contact[Zone == FALSE & Swing == TRUE],na.rm = TRUE),
215
- "OSwing%" = mean(Swing[Zone == FALSE],na.rm = TRUE),
216
- "Avg EV" = mean(ExitSpeed[BBE == TRUE],na.rm = TRUE),
217
- "EV90" = quantile(ExitSpeed[BBE == TRUE],.9,na.rm = TRUE),
218
- "Max EV" = max(ExitSpeed[BBE == TRUE],na.rm = TRUE),
219
- "Max EV" = ifelse(is.infinite(`Max EV`),NA,`Max EV`),
220
- "GB%" = mean(GB[BBE == TRUE],na.rm = TRUE),
221
- "LD%" = mean(LD[BBE == TRUE],na.rm = TRUE),
222
- "FB%" = mean(FB[BBE == TRUE],na.rm = TRUE),
223
- "AVG" = round(sum(Hit,na.rm = TRUE) / sum(AB,na.rm = TRUE),digits = 3),
224
- "OBP" = round((sum(Hit,na.rm = TRUE) + sum(Walk,na.rm = TRUE) + sum(HBP,na.rm = TRUE))/
225
- sum(PA,na.rm = TRUE),digits = 3),
226
- "SLG" = (round(sum(Single,na.rm = TRUE) + sum(Double,na.rm = TRUE) * 2 +
227
- sum(Triple,na.rm = TRUE) * 3 + sum(HR,na.rm = TRUE)))/sum(AB,na.rm = TRUE))%>%
228
- ungroup()%>%
229
- gt() %>%
230
- gt_theme_tim() %>%
231
- fmt_number(columns = `Avg EV`:`Max EV`,decimals = 1) %>%
232
- cols_width(Count:Pitches ~ px(70),
233
- everything() ~ px(85)) %>%
234
- cols_align(align = "center") %>%
235
- fmt_number(columns = AVG:SLG,decimals = 3) %>%
236
- fmt_percent(columns = ends_with("%")) %>%
237
- sub_missing() %>%
238
- #gt_theme_savant() %>%
239
- opt_interactive(
240
- use_compact_mode = TRUE,
241
- use_pagination = FALSE
242
- )
243
- })
244
- output$PitchFilter <- render_gt({
245
- tes <- test %>%
246
- filter(Pitcher == input$player) %>%
247
- group_by(AutoPitchType) %>%
248
- summarise(
249
- Pitches = n(),
250
- # BBE = sum(BBE,na.rm = TRUE),
251
- "Usage%" = n() / nrow(.), # Added Usage% calculation
252
- "Whiff%" = mean(Whiff, na.rm = TRUE),
253
- "CSW%" = mean(CSW, na.rm = TRUE),
254
- "Zone%" = mean(Zone, na.rm = TRUE),
255
- "ZCon%" = mean(Contact[Zone == TRUE & Swing == TRUE], na.rm = TRUE),
256
- "ZSwing%" = mean(Swing[Zone == TRUE], na.rm = TRUE),
257
- "OCon%" = mean(Contact[Zone == FALSE & Swing == TRUE], na.rm = TRUE),
258
- "OSwing%" = mean(Swing[Zone == FALSE], na.rm = TRUE),
259
- "Avg EV" = mean(ExitSpeed[BBE == TRUE], na.rm = TRUE),
260
- "EV90" = quantile(ExitSpeed[BBE == TRUE], .9, na.rm = TRUE),
261
- "Max EV" = max(ExitSpeed[BBE == TRUE], na.rm = TRUE),
262
- "Max EV" = ifelse(is.infinite(`Max EV`), NA, `Max EV`),
263
- "GB%" = mean(GB[BBE == TRUE], na.rm = TRUE),
264
- "LD%" = mean(LD[BBE == TRUE], na.rm = TRUE),
265
- "FB%" = mean(FB[BBE == TRUE], na.rm = TRUE),
266
- "AVG" = round(sum(Hit, na.rm = TRUE) / sum(AB, na.rm = TRUE), digits = 3),
267
- "OBP" = round((sum(Hit, na.rm = TRUE) + sum(Walk, na.rm = TRUE) + sum(HBP, na.rm = TRUE)) /
268
- sum(PA, na.rm = TRUE), digits = 3),
269
- "SLG" = (round(sum(Single, na.rm = TRUE) + sum(Double, na.rm = TRUE) * 2 +
270
- sum(Triple, na.rm = TRUE) * 3 + sum(HR, na.rm = TRUE))) / sum(AB, na.rm = TRUE)
271
- ) %>%
272
- ungroup() %>%
273
- arrange(desc(Pitches)) %>%
274
- gt() %>%
275
- gt_theme_tim() %>%
276
- fmt_number(columns = `Avg EV`:`Max EV`, decimals = 1) %>%
277
- cols_label(AutoPitchType = "Type") %>%
278
- cols_width(
279
- AutoPitchType ~ px(100),
280
- Pitches ~ px(70),
281
- everything() ~ px(85)
282
- ) %>%
283
- cols_align(align = "center") %>%
284
- fmt_number(columns = AVG:SLG, decimals = 3) %>%
285
- fmt_percent(columns = ends_with("%")) %>%
286
- sub_missing() %>%
287
- opt_interactive(
288
- use_compact_mode = TRUE,
289
- use_pagination = FALSE
290
- )
291
- })
292
- output$PitchSideFilter <- render_gt({
293
- test <- test %>%
294
- filter(Pitcher == input$player) %>%
295
- group_by(BatterSide) %>%
296
- mutate(total_side = n()) %>%
297
- ungroup() %>%
298
- group_by(AutoPitchType, BatterSide) %>%
299
- summarise(
300
- Pitches = n(),
301
- #BBE = sum(BBE,na.rm = TRUE),
302
- "Usage%" = (n() / first(total_side)),
303
- "Whiff%" = mean(Whiff, na.rm = TRUE),
304
- "CSW%" = mean(CSW, na.rm = TRUE),
305
- "Zone%" = mean(Zone, na.rm = TRUE),
306
- "ZCon%" = mean(Contact[Zone == TRUE & Swing == TRUE], na.rm = TRUE),
307
- "ZSwing%" = mean(Swing[Zone == TRUE], na.rm = TRUE),
308
- "OCon%" = mean(Contact[Zone == FALSE & Swing == TRUE], na.rm = TRUE),
309
- "OSwing%" = mean(Swing[Zone == FALSE], na.rm = TRUE),
310
- "Avg EV" = mean(ExitSpeed[BBE == TRUE], na.rm = TRUE),
311
- "EV90" = quantile(ExitSpeed[BBE == TRUE], .9, na.rm = TRUE),
312
- "Max EV" = max(ExitSpeed[BBE == TRUE], na.rm = TRUE),
313
- "Max EV" = ifelse(is.infinite(`Max EV`), NA, `Max EV`),
314
- "GB%" = mean(GB[BBE == TRUE], na.rm = TRUE),
315
- "LD%" = mean(LD[BBE == TRUE], na.rm = TRUE),
316
- "FB%" = mean(FB[BBE == TRUE], na.rm = TRUE),
317
- "AVG" = round(sum(Hit, na.rm = TRUE) / sum(AB, na.rm = TRUE), digits = 3),
318
- "OBP" = round((sum(Hit, na.rm = TRUE) + sum(Walk, na.rm = TRUE) + sum(HBP, na.rm = TRUE)) /
319
- sum(PA, na.rm = TRUE), digits = 3),
320
- "SLG" = (round(sum(Single, na.rm = TRUE) + sum(Double, na.rm = TRUE) * 2 +
321
- sum(Triple, na.rm = TRUE) * 3 + sum(HR, na.rm = TRUE))) / sum(AB, na.rm = TRUE)
322
- ) %>%
323
- ungroup() %>%
324
- arrange(desc(BatterSide),desc(Pitches)) %>%
325
- gt() %>%
326
- gt_theme_tim() %>%
327
- fmt_number(columns = `Avg EV`:`Max EV`, decimals = 1) %>%
328
- cols_label(AutoPitchType = "Type", BatterSide = "Side") %>%
329
- cols_width(
330
- AutoPitchType ~ px(100),
331
- Pitches ~ px(70),
332
- BatterSide ~ px(70),
333
- everything() ~ px(85)
334
- ) %>%
335
- cols_align(align = "center") %>%
336
- fmt_number(columns = AVG:SLG, decimals = 3) %>%
337
- fmt_percent(columns = ends_with("%")) %>%
338
- sub_missing() %>%
339
- opt_interactive(
340
- use_compact_mode = TRUE,
341
- use_pagination = FALSE
342
- )
343
- })
344
- output$InningFilter <- render_gt({
345
- test <- test %>% filter(Pitcher == input$player) %>% group_by(Inning) %>%
346
- summarise(
347
- Pitches = n(),
348
- #BBE = sum(BBE,na.rm = TRUE),
349
- "Whiff%" = mean(Whiff,na.rm = TRUE),
350
- "CSW%" = mean(CSW,na.rm = TRUE),
351
- "Zone%" = mean(Zone,na.rm = TRUE),
352
- "ZCon%" = mean(Contact[Zone == TRUE & Swing == TRUE],na.rm = TRUE),
353
- "ZSwing%" = mean(Swing[Zone == TRUE],na.rm = TRUE),
354
- "OCon%" = mean(Contact[Zone == FALSE & Swing == TRUE],na.rm = TRUE),
355
- "OSwing%" = mean(Swing[Zone == FALSE],na.rm = TRUE),
356
- "Avg EV" = mean(ExitSpeed[BBE == TRUE],na.rm = TRUE),
357
- "EV90" = quantile(ExitSpeed[BBE == TRUE],.9,na.rm = TRUE),
358
- "Max EV" = max(ExitSpeed[BBE == TRUE],na.rm = TRUE),
359
- "Max EV" = ifelse(is.infinite(`Max EV`),NA,`Max EV`),
360
- "GB%" = mean(GB[BBE == TRUE],na.rm = TRUE),
361
- "LD%" = mean(LD[BBE == TRUE],na.rm = TRUE),
362
- "FB%" = mean(FB[BBE == TRUE],na.rm = TRUE),
363
- "AVG" = round(sum(Hit,na.rm = TRUE) / sum(AB,na.rm = TRUE),digits = 3),
364
- "OBP" = round((sum(Hit,na.rm = TRUE) + sum(Walk,na.rm = TRUE) + sum(HBP,na.rm = TRUE))/
365
- sum(PA,na.rm = TRUE),digits = 3),
366
- "SLG" = (round(sum(Single,na.rm = TRUE) + sum(Double,na.rm = TRUE) * 2 +
367
- sum(Triple,na.rm = TRUE) * 3 + sum(HR,na.rm = TRUE)))/sum(AB,na.rm = TRUE))%>%
368
- ungroup()%>%
369
- gt() %>%
370
- gt_theme_tim() %>%
371
- fmt_number(columns = `Avg EV`:`Max EV`,decimals = 1) %>%
372
- cols_width(Inning:Pitches ~ px(70),
373
- everything() ~ px(85)) %>%
374
- cols_align(align = "center") %>%
375
- fmt_number(columns = AVG:SLG,decimals = 3) %>%
376
- fmt_percent(columns = ends_with("%")) %>%
377
- sub_missing() %>%
378
- #gt_theme_savant() %>%
379
- opt_interactive(
380
- use_compact_mode = TRUE,
381
- use_pagination = FALSE
382
- )
383
- })
384
- output$SideFilter <- render_gt({
385
- test1 <- test %>% filter(Pitcher == input$player) %>% group_by(BatterSide) %>%
386
- summarise(
387
- Pitches = n(),
388
- #BBE = sum(BBE,na.rm = TRUE),
389
- "Whiff%" = mean(Whiff,na.rm = TRUE),
390
- "CSW%" = mean(CSW,na.rm = TRUE),
391
- "Zone%" = mean(Zone,na.rm = TRUE),
392
- "ZCon%" = mean(Contact[Zone == TRUE & Swing == TRUE],na.rm = TRUE),
393
- "ZSwing%" = mean(Swing[Zone == TRUE],na.rm = TRUE),
394
- "OCon%" = mean(Contact[Zone == FALSE & Swing == TRUE],na.rm = TRUE),
395
- "OSwing%" = mean(Swing[Zone == FALSE],na.rm = TRUE),
396
- "Avg EV" = mean(ExitSpeed[BBE == TRUE],na.rm = TRUE),
397
- "EV90" = quantile(ExitSpeed[BBE == TRUE],.9,na.rm = TRUE),
398
- "Max EV" = max(ExitSpeed[BBE == TRUE],na.rm = TRUE),
399
- "Max EV" = ifelse(is.infinite(`Max EV`),NA,`Max EV`),
400
- "GB%" = mean(GB[BBE == TRUE],na.rm = TRUE),
401
- "LD%" = mean(LD[BBE == TRUE],na.rm = TRUE),
402
- "FB%" = mean(FB[BBE == TRUE],na.rm = TRUE),
403
- "AVG" = round(sum(Hit,na.rm = TRUE) / sum(AB,na.rm = TRUE),digits = 3),
404
- "OBP" = round((sum(Hit,na.rm = TRUE) + sum(Walk,na.rm = TRUE) + sum(HBP,na.rm = TRUE))/
405
- sum(PA,na.rm = TRUE),digits = 3),
406
- "SLG" = (round(sum(Single,na.rm = TRUE) + sum(Double,na.rm = TRUE) * 2 +
407
- sum(Triple,na.rm = TRUE) * 3 + sum(HR,na.rm = TRUE)))/sum(AB,na.rm = TRUE))%>%
408
- ungroup()
409
- test2 <- test %>% mutate(BatterSide = "Both") %>%filter(Pitcher == "Beam, Drew") %>% group_by(BatterSide) %>%
410
- summarise(
411
- Pitches = n(),
412
- #BBE = sum(BBE,na.rm = TRUE),
413
- "Whiff%" = mean(Whiff,na.rm = TRUE),
414
- "CSW%" = mean(CSW,na.rm = TRUE),
415
- "Zone%" = mean(Zone,na.rm = TRUE),
416
- "ZCon%" = mean(Contact[Zone == TRUE & Swing == TRUE],na.rm = TRUE),
417
- "ZSwing%" = mean(Swing[Zone == TRUE],na.rm = TRUE),
418
- "OCon%" = mean(Contact[Zone == FALSE & Swing == TRUE],na.rm = TRUE),
419
- "OSwing%" = mean(Swing[Zone == FALSE],na.rm = TRUE),
420
- "Avg EV" = mean(ExitSpeed[BBE == TRUE],na.rm = TRUE),
421
- "EV90" = quantile(ExitSpeed[BBE == TRUE],.9,na.rm = TRUE),
422
- "Max EV" = max(ExitSpeed[BBE == TRUE],na.rm = TRUE),
423
- "Max EV" = ifelse(is.infinite(`Max EV`),NA,`Max EV`),
424
- "GB%" = mean(GB[BBE == TRUE],na.rm = TRUE),
425
- "LD%" = mean(LD[BBE == TRUE],na.rm = TRUE),
426
- "FB%" = mean(FB[BBE == TRUE],na.rm = TRUE),
427
- "AVG" = round(sum(Hit,na.rm = TRUE) / sum(AB,na.rm = TRUE),digits = 3),
428
- "OBP" = round((sum(Hit,na.rm = TRUE) + sum(Walk,na.rm = TRUE) + sum(HBP,na.rm = TRUE))/
429
- sum(PA,na.rm = TRUE),digits = 3),
430
- "SLG" = (round(sum(Single,na.rm = TRUE) + sum(Double,na.rm = TRUE) * 2 +
431
- sum(Triple,na.rm = TRUE) * 3 + sum(HR,na.rm = TRUE)))/sum(AB,na.rm = TRUE))%>%
432
- ungroup()
433
- test <- rbind(test1,test2)
434
- test %>%
435
- gt() %>%
436
- gt_theme_tim() %>%
437
- fmt_number(columns = `Avg EV`:`Max EV`,decimals = 1) %>%
438
- cols_width(BatterSide:Pitches ~ px(70),
439
- everything() ~ px(85)) %>%
440
- cols_align(align = "center") %>%
441
- cols_label(BatterSide = "Side") %>%
442
- fmt_number(columns = AVG:SLG,decimals = 3) %>%
443
- fmt_percent(columns = ends_with("%")) %>%
444
- sub_missing() %>%
445
- #gt_theme_savant() %>%
446
- opt_interactive(
447
- use_compact_mode = TRUE,
448
- use_pagination = FALSE
449
- )
450
-
451
- })
452
- output$slashline <- render_gt({
453
- test <- test %>% filter(Pitcher == input$player) %>%
454
- summarise(
455
- Pitches = n(),
456
- `1B` = sum(Single,na.rm = TRUE),
457
- `2B` = sum(Double,na.rm = TRUE),
458
- `3B` = sum(Triple,na.rm = TRUE),
459
- HR = sum(HR,na.rm = TRUE),
460
- SO = sum(Strikeout,na.rm = TRUE),
461
- BB = sum(Walk,na.rm = TRUE),
462
- Whiffs = sum(Whiff,na.rm = TRUE),
463
- `Hard Hits` = sum(HardHit,na.rm = TRUE)
464
- )%>%
465
- ungroup()%>%
466
- gt() %>%
467
- gt_theme_tim() %>%
468
- cols_align(align = "center") %>%
469
- # gt_theme_savant() %>%
470
- opt_interactive(
471
- use_compact_mode = TRUE,
472
- use_pagination = FALSE
473
- )
474
- })
475
- }
476
-
477
- # Run the application
478
- shinyApp(ui = ui, server = server)
 
1
+ library(shiny)
2
+ library(gt)
3
+ library(dplyr)
4
+ library(shinyjs)
5
+ library(shinyauthr)
6
+ library(gtExtras)
7
+ library(bslib)
8
+
9
+ Bean <- read.csv('Beam.csv')
10
+
11
+ test <- Beam %>%
12
+ select(Date,PitchofPA,Pitcher,PitcherId,PitcherThrows,PitcherTeam,Batter,BatterId,
13
+ BatterSide,BatterTeam,Inning,`Top/Bottom`,Outs,Balls,Strikes,TaggedPitchType,
14
+ AutoPitchType,PitchCall,TaggedHitType,KorBB,PlayResult,OutsOnPlay,RunsScored,
15
+ RelSpeed,VertRelAngle,HorzRelAngle,SpinRate,SpinAxis,Tilt,RelHeight,RelSide,
16
+ Extension,InducedVertBreak,HorzBreak,PlateLocHeight,PlateLocSide,VertApprAngle,
17
+ HorzApprAngle,ExitSpeed,Angle,Direction,Distance,pfxx,pfxz,x0,z0,vx0,vy0,vz0,
18
+ ax0,ay0,az0,Level,League,ContactPositionX,ContactPositionY,ContactPositionZ,
19
+ SpinAxis3dTransverseAngle,SpinAxis3dLongitudinalAngle,SpinAxis3dTilt,
20
+ SpinAxis3dSpinEfficiency,SpinAxis3dSeamOrientationRotationX,
21
+ SpinAxis3dSeamOrientationRotationY,SpinAxis3dSeamOrientationRotationZ)
22
+ test <- test %>%
23
+ mutate("Hit" = case_when(PlayResult %in% c("Single","Double","Triple","HomeRun") ~ TRUE,TRUE ~ FALSE),
24
+ "CallStrike" = case_when(PitchCall %in% c("StrikeCalled") ~ TRUE, TRUE ~ FALSE),
25
+ "Whiff" = case_when(PitchCall %in% c("StrikeSwinging") ~ TRUE, TRUE ~ FALSE),
26
+ "CSW" = CallStrike + Whiff,
27
+ "Contact" = case_when(PitchCall %in% c("FoulBall","FouBallNotFieldable","InPlay") ~ TRUE, TRUE ~ FALSE),
28
+ "GB" = case_when(TaggedHitType %in% c('GroundBall') ~ TRUE, TRUE ~ FALSE),
29
+ "LD" = case_when(TaggedHitType %in% c('LineDrive') ~ TRUE, TRUE ~ FALSE),
30
+ "FB" = case_when(TaggedHitType %in% c ("FlyBall") ~ TRUE, TRUE ~ FALSE),
31
+ "PopU" = case_when(TaggedHitType %in% c ("Popup") ~ TRUE, TRUE ~ FALSE),
32
+ "Swing" = Whiff + Contact,
33
+ "BBE" = GB + LD + FB + PopU,
34
+ "HardHit" = ifelse(ExitSpeed >= 95,TRUE,FALSE),
35
+ "Ball" = case_when(PitchCall %in% c("BallCalled","BallinDirt") ~ TRUE, TRUE ~ FALSE),
36
+ "Single" = case_when(PlayResult %in% c("Single") ~ TRUE, TRUE ~ FALSE),
37
+ "Double" = case_when(PlayResult %in% c("Double") ~ TRUE, TRUE ~ FALSE),
38
+ "Triple" = case_when(PlayResult %in% c("Triple") ~ TRUE, TRUE ~ FALSE),
39
+ "HR" = case_when(PlayResult %in% c("HomeRun") ~ TRUE, TRUE ~ FALSE),
40
+ "Sac" = case_when(PlayResult %in% c("Sacrifice") ~ TRUE, TRUE ~ FALSE),
41
+ "HBP" = case_when(PitchCall %in% c("HitByPitch") ~ TRUE, TRUE ~ FALSE),
42
+ "Error" = case_when(PlayResult %in% c("Error") ~ TRUE, TRUE ~ FALSE),
43
+ "FC"= case_when(PlayResult %in% c("FieldersChoice") ~ TRUE, TRUE ~ FALSE),
44
+ "Out" = case_when(PlayResult %in% c ("Out") ~ TRUE, TRUE ~ FALSE),
45
+ "BIP" = Single + Double + Triple + HR + Sac + Error + Out + FC,
46
+ "Count" = paste0(Balls,"-",Strikes),
47
+ "Strikeout" = ifelse(KorBB == "Strikeout",TRUE,FALSE),
48
+ "Walk" = ifelse(KorBB == "Walk",TRUE,FALSE),
49
+ "Zone" = case_when(between(PlateLocSide,-.825,.825) & between(PlateLocHeight,1.45,3.45) ~ TRUE, TRUE ~ FALSE),
50
+ "AB" = Strikeout + BIP - Sac,
51
+ "PA" = Strikeout + BIP + Walk + HBP
52
+ )
53
+
54
+
55
+ gt_theme_tim <- function(gt_object,...) {
56
+
57
+ stopifnot(`'gt_object' must be a 'gt_tbl', have you accidentally passed raw data?` = "gt_tbl" %in%
58
+ class(gt_object))
59
+
60
+ table_id <- subset(gt_object[['_options']], parameter == 'table_id')$value[[1]]
61
+
62
+ if (is.na(table_id)) {
63
+ table_id <- gt::random_id()
64
+ opt_position <- which("table_id" %in% gt_object[["_options"]][["parameter"]])[[1]]
65
+ gt_object[["_options"]][["value"]][[opt_position]] <- table_id
66
+ }
67
+
68
+ gt_object %>%
69
+ # cell body
70
+ gt::tab_style(
71
+ locations = gt::cells_body(),
72
+ style = gt::cell_text(font = "Arial", size = px(14))
73
+ ) %>%
74
+ # col. headers
75
+ gt::tab_style(
76
+ locations = gt::cells_column_labels(),
77
+ style = gt::cell_text(weight = 'bold', font = "Arial", size = px(14))
78
+ ) %>%
79
+ # group rows
80
+ gt::tab_style(
81
+ locations = gt::cells_row_groups(),
82
+ style = list(
83
+ gt::cell_text(font = "Arial", weight = 650, size = px(14), color = "#FFFDF5"),
84
+ gt::cell_fill(color = "#000000")
85
+ )
86
+ ) %>%
87
+ # footnote
88
+ gt::tab_style(
89
+ locations = gt::cells_footnotes(),
90
+ style = gt::cell_text(font = "Arial", size = px(12))
91
+ ) %>%
92
+ # title
93
+ gt::tab_style(
94
+ locations = gt::cells_title('title'),
95
+ style = gt::cell_text(weight = 'bold', font = "Arial", size = px(18))
96
+ ) %>%
97
+ # subtitle
98
+ gt::tab_style(
99
+ locations = gt::cells_title('subtitle'),
100
+ style = gt::cell_text(font = "Arial", size = px(14))
101
+ ) %>%
102
+ # caption
103
+ gt::tab_style(
104
+ locations = gt::cells_source_notes(),
105
+ style = gt::cell_text(font = "Arial", size = px(12))
106
+ ) %>%
107
+ # spanner
108
+ gt::tab_style(
109
+ locations = gt::cells_column_spanners(),
110
+ style = gt::cell_text(font = "Arial", weight = 650, size = px(8))
111
+ ) %>%
112
+ gt::tab_options(
113
+ data_row.padding = 1,
114
+ table_body.hlines.color = "transparent",
115
+ column_labels.border.top.color = 'black',
116
+ column_labels.border.top.width = px(1),
117
+ column_labels.border.bottom.style = 'none',
118
+ #column_labels.background.color = "orange",
119
+ row_group.border.top.style = "none",
120
+ row_group.border.top.color = "black",
121
+ row_group.border.bottom.width = px(1),
122
+ row_group.border.bottom.color = "black",
123
+ row_group.border.bottom.style = 'solid',
124
+ row_group.padding = px(1.5),
125
+ heading.align = 'center',
126
+ heading.border.bottom.style = "none",
127
+ table_body.border.top.style = "none",
128
+ table_body.border.bottom.color = "white",
129
+ table.border.bottom.style = 'none',
130
+ table.border.top.style = 'none',
131
+ source_notes.border.lr.style = "none",
132
+ ...
133
+ ) %>%
134
+ gt::opt_row_striping()
135
+ }
136
+
137
+ user_base <- tibble::tibble(
138
+ user = c("TrentR", "user2"),
139
+ password = sapply(c("Caprisun", "pass2")),
140
+ permissions = c("admin", "standard"),
141
+ name = c("User One", "User Two")
142
+ )
143
+
144
+ # Define UI for application that draws a histogram
145
+ ui <- fluidPage(
146
+ div(class = "pull-right", shinyauthr::logoutUI(id = "logout")),
147
+
148
+ # login section
149
+ shinyauthr::loginUI(id = "login"),
150
+
151
+ div(
152
+ id = "bar",
153
+ # Application title
154
+ titlePanel("College Pitcher"),
155
+
156
+ # Sidebar layout
157
+ sidebarLayout(
158
+ sidebarPanel(
159
+ selectInput("player",
160
+ "Select Player",
161
+ choices = unique(test$Pitcher)),
162
+ width = 3
163
+ ),
164
+
165
+ mainPanel(
166
+ tabsetPanel(
167
+ tabPanel("Splits",
168
+ gt_output("CountFilter"),
169
+ gt_output("PitchFilter"),
170
+ gt_output("PitchSideFilter"),
171
+ gt_output("InningFilter"),
172
+ gt_output("SideFilter")
173
+ )
174
+ ),
175
+ width = 9
176
+ )
177
+ )
178
+ ) %>% shinyjs::hidden()
179
+ )
180
+
181
+ # Define server logic required to draw a histogram
182
+ server <- function(input, output) {
183
+
184
+ credentials <- shinyauthr::loginServer(
185
+ id = "login",
186
+ data = user_base,
187
+ user_col = user,
188
+ pwd_col = password,
189
+ sodium_hashed = FALSE,
190
+ log_out = reactive(logout_init())
191
+ )
192
+
193
+ # Logout to hide
194
+ logout_init <- shinyauthr::logoutServer(
195
+ id = "logout",
196
+ active = reactive(credentials()$user_auth)
197
+ )
198
+
199
+ observe({
200
+ req(credentials()$user_auth)
201
+ shinyjs::show(id = "bar")
202
+ })
203
+
204
+ output$CountFilter <- render_gt({
205
+ test <- test %>% filter(Pitcher == input$player) %>% group_by(Count) %>%
206
+ summarise(
207
+ Pitches = n(),
208
+ #BBE = sum(BBE,na.rm = TRUE),
209
+ "Whiff%" = mean(Whiff,na.rm = TRUE),
210
+ "CSW%" = mean(CSW,na.rm = TRUE),
211
+ "Zone%" = mean(Zone,na.rm = TRUE),
212
+ "ZCon%" = mean(Contact[Zone == TRUE & Swing == TRUE],na.rm = TRUE),
213
+ "ZSwing%" = mean(Swing[Zone == TRUE],na.rm = TRUE),
214
+ "OCon%" = mean(Contact[Zone == FALSE & Swing == TRUE],na.rm = TRUE),
215
+ "OSwing%" = mean(Swing[Zone == FALSE],na.rm = TRUE),
216
+ "Avg EV" = mean(ExitSpeed[BBE == TRUE],na.rm = TRUE),
217
+ "EV90" = quantile(ExitSpeed[BBE == TRUE],.9,na.rm = TRUE),
218
+ "Max EV" = max(ExitSpeed[BBE == TRUE],na.rm = TRUE),
219
+ "Max EV" = ifelse(is.infinite(`Max EV`),NA,`Max EV`),
220
+ "GB%" = mean(GB[BBE == TRUE],na.rm = TRUE),
221
+ "LD%" = mean(LD[BBE == TRUE],na.rm = TRUE),
222
+ "FB%" = mean(FB[BBE == TRUE],na.rm = TRUE),
223
+ "AVG" = round(sum(Hit,na.rm = TRUE) / sum(AB,na.rm = TRUE),digits = 3),
224
+ "OBP" = round((sum(Hit,na.rm = TRUE) + sum(Walk,na.rm = TRUE) + sum(HBP,na.rm = TRUE))/
225
+ sum(PA,na.rm = TRUE),digits = 3),
226
+ "SLG" = (round(sum(Single,na.rm = TRUE) + sum(Double,na.rm = TRUE) * 2 +
227
+ sum(Triple,na.rm = TRUE) * 3 + sum(HR,na.rm = TRUE)))/sum(AB,na.rm = TRUE))%>%
228
+ ungroup()%>%
229
+ gt() %>%
230
+ gt_theme_tim() %>%
231
+ fmt_number(columns = `Avg EV`:`Max EV`,decimals = 1) %>%
232
+ cols_width(Count:Pitches ~ px(70),
233
+ everything() ~ px(85)) %>%
234
+ cols_align(align = "center") %>%
235
+ fmt_number(columns = AVG:SLG,decimals = 3) %>%
236
+ fmt_percent(columns = ends_with("%")) %>%
237
+ sub_missing() %>%
238
+ #gt_theme_savant() %>%
239
+ opt_interactive(
240
+ use_compact_mode = TRUE,
241
+ use_pagination = FALSE
242
+ )
243
+ })
244
+ output$PitchFilter <- render_gt({
245
+ tes <- test %>%
246
+ filter(Pitcher == input$player) %>%
247
+ group_by(AutoPitchType) %>%
248
+ summarise(
249
+ Pitches = n(),
250
+ # BBE = sum(BBE,na.rm = TRUE),
251
+ "Usage%" = n() / nrow(.), # Added Usage% calculation
252
+ "Whiff%" = mean(Whiff, na.rm = TRUE),
253
+ "CSW%" = mean(CSW, na.rm = TRUE),
254
+ "Zone%" = mean(Zone, na.rm = TRUE),
255
+ "ZCon%" = mean(Contact[Zone == TRUE & Swing == TRUE], na.rm = TRUE),
256
+ "ZSwing%" = mean(Swing[Zone == TRUE], na.rm = TRUE),
257
+ "OCon%" = mean(Contact[Zone == FALSE & Swing == TRUE], na.rm = TRUE),
258
+ "OSwing%" = mean(Swing[Zone == FALSE], na.rm = TRUE),
259
+ "Avg EV" = mean(ExitSpeed[BBE == TRUE], na.rm = TRUE),
260
+ "EV90" = quantile(ExitSpeed[BBE == TRUE], .9, na.rm = TRUE),
261
+ "Max EV" = max(ExitSpeed[BBE == TRUE], na.rm = TRUE),
262
+ "Max EV" = ifelse(is.infinite(`Max EV`), NA, `Max EV`),
263
+ "GB%" = mean(GB[BBE == TRUE], na.rm = TRUE),
264
+ "LD%" = mean(LD[BBE == TRUE], na.rm = TRUE),
265
+ "FB%" = mean(FB[BBE == TRUE], na.rm = TRUE),
266
+ "AVG" = round(sum(Hit, na.rm = TRUE) / sum(AB, na.rm = TRUE), digits = 3),
267
+ "OBP" = round((sum(Hit, na.rm = TRUE) + sum(Walk, na.rm = TRUE) + sum(HBP, na.rm = TRUE)) /
268
+ sum(PA, na.rm = TRUE), digits = 3),
269
+ "SLG" = (round(sum(Single, na.rm = TRUE) + sum(Double, na.rm = TRUE) * 2 +
270
+ sum(Triple, na.rm = TRUE) * 3 + sum(HR, na.rm = TRUE))) / sum(AB, na.rm = TRUE)
271
+ ) %>%
272
+ ungroup() %>%
273
+ arrange(desc(Pitches)) %>%
274
+ gt() %>%
275
+ gt_theme_tim() %>%
276
+ fmt_number(columns = `Avg EV`:`Max EV`, decimals = 1) %>%
277
+ cols_label(AutoPitchType = "Type") %>%
278
+ cols_width(
279
+ AutoPitchType ~ px(100),
280
+ Pitches ~ px(70),
281
+ everything() ~ px(85)
282
+ ) %>%
283
+ cols_align(align = "center") %>%
284
+ fmt_number(columns = AVG:SLG, decimals = 3) %>%
285
+ fmt_percent(columns = ends_with("%")) %>%
286
+ sub_missing() %>%
287
+ opt_interactive(
288
+ use_compact_mode = TRUE,
289
+ use_pagination = FALSE
290
+ )
291
+ })
292
+ output$PitchSideFilter <- render_gt({
293
+ test <- test %>%
294
+ filter(Pitcher == input$player) %>%
295
+ group_by(BatterSide) %>%
296
+ mutate(total_side = n()) %>%
297
+ ungroup() %>%
298
+ group_by(AutoPitchType, BatterSide) %>%
299
+ summarise(
300
+ Pitches = n(),
301
+ #BBE = sum(BBE,na.rm = TRUE),
302
+ "Usage%" = (n() / first(total_side)),
303
+ "Whiff%" = mean(Whiff, na.rm = TRUE),
304
+ "CSW%" = mean(CSW, na.rm = TRUE),
305
+ "Zone%" = mean(Zone, na.rm = TRUE),
306
+ "ZCon%" = mean(Contact[Zone == TRUE & Swing == TRUE], na.rm = TRUE),
307
+ "ZSwing%" = mean(Swing[Zone == TRUE], na.rm = TRUE),
308
+ "OCon%" = mean(Contact[Zone == FALSE & Swing == TRUE], na.rm = TRUE),
309
+ "OSwing%" = mean(Swing[Zone == FALSE], na.rm = TRUE),
310
+ "Avg EV" = mean(ExitSpeed[BBE == TRUE], na.rm = TRUE),
311
+ "EV90" = quantile(ExitSpeed[BBE == TRUE], .9, na.rm = TRUE),
312
+ "Max EV" = max(ExitSpeed[BBE == TRUE], na.rm = TRUE),
313
+ "Max EV" = ifelse(is.infinite(`Max EV`), NA, `Max EV`),
314
+ "GB%" = mean(GB[BBE == TRUE], na.rm = TRUE),
315
+ "LD%" = mean(LD[BBE == TRUE], na.rm = TRUE),
316
+ "FB%" = mean(FB[BBE == TRUE], na.rm = TRUE),
317
+ "AVG" = round(sum(Hit, na.rm = TRUE) / sum(AB, na.rm = TRUE), digits = 3),
318
+ "OBP" = round((sum(Hit, na.rm = TRUE) + sum(Walk, na.rm = TRUE) + sum(HBP, na.rm = TRUE)) /
319
+ sum(PA, na.rm = TRUE), digits = 3),
320
+ "SLG" = (round(sum(Single, na.rm = TRUE) + sum(Double, na.rm = TRUE) * 2 +
321
+ sum(Triple, na.rm = TRUE) * 3 + sum(HR, na.rm = TRUE))) / sum(AB, na.rm = TRUE)
322
+ ) %>%
323
+ ungroup() %>%
324
+ arrange(desc(BatterSide),desc(Pitches)) %>%
325
+ gt() %>%
326
+ gt_theme_tim() %>%
327
+ fmt_number(columns = `Avg EV`:`Max EV`, decimals = 1) %>%
328
+ cols_label(AutoPitchType = "Type", BatterSide = "Side") %>%
329
+ cols_width(
330
+ AutoPitchType ~ px(100),
331
+ Pitches ~ px(70),
332
+ BatterSide ~ px(70),
333
+ everything() ~ px(85)
334
+ ) %>%
335
+ cols_align(align = "center") %>%
336
+ fmt_number(columns = AVG:SLG, decimals = 3) %>%
337
+ fmt_percent(columns = ends_with("%")) %>%
338
+ sub_missing() %>%
339
+ opt_interactive(
340
+ use_compact_mode = TRUE,
341
+ use_pagination = FALSE
342
+ )
343
+ })
344
+ output$InningFilter <- render_gt({
345
+ test <- test %>% filter(Pitcher == input$player) %>% group_by(Inning) %>%
346
+ summarise(
347
+ Pitches = n(),
348
+ #BBE = sum(BBE,na.rm = TRUE),
349
+ "Whiff%" = mean(Whiff,na.rm = TRUE),
350
+ "CSW%" = mean(CSW,na.rm = TRUE),
351
+ "Zone%" = mean(Zone,na.rm = TRUE),
352
+ "ZCon%" = mean(Contact[Zone == TRUE & Swing == TRUE],na.rm = TRUE),
353
+ "ZSwing%" = mean(Swing[Zone == TRUE],na.rm = TRUE),
354
+ "OCon%" = mean(Contact[Zone == FALSE & Swing == TRUE],na.rm = TRUE),
355
+ "OSwing%" = mean(Swing[Zone == FALSE],na.rm = TRUE),
356
+ "Avg EV" = mean(ExitSpeed[BBE == TRUE],na.rm = TRUE),
357
+ "EV90" = quantile(ExitSpeed[BBE == TRUE],.9,na.rm = TRUE),
358
+ "Max EV" = max(ExitSpeed[BBE == TRUE],na.rm = TRUE),
359
+ "Max EV" = ifelse(is.infinite(`Max EV`),NA,`Max EV`),
360
+ "GB%" = mean(GB[BBE == TRUE],na.rm = TRUE),
361
+ "LD%" = mean(LD[BBE == TRUE],na.rm = TRUE),
362
+ "FB%" = mean(FB[BBE == TRUE],na.rm = TRUE),
363
+ "AVG" = round(sum(Hit,na.rm = TRUE) / sum(AB,na.rm = TRUE),digits = 3),
364
+ "OBP" = round((sum(Hit,na.rm = TRUE) + sum(Walk,na.rm = TRUE) + sum(HBP,na.rm = TRUE))/
365
+ sum(PA,na.rm = TRUE),digits = 3),
366
+ "SLG" = (round(sum(Single,na.rm = TRUE) + sum(Double,na.rm = TRUE) * 2 +
367
+ sum(Triple,na.rm = TRUE) * 3 + sum(HR,na.rm = TRUE)))/sum(AB,na.rm = TRUE))%>%
368
+ ungroup()%>%
369
+ gt() %>%
370
+ gt_theme_tim() %>%
371
+ fmt_number(columns = `Avg EV`:`Max EV`,decimals = 1) %>%
372
+ cols_width(Inning:Pitches ~ px(70),
373
+ everything() ~ px(85)) %>%
374
+ cols_align(align = "center") %>%
375
+ fmt_number(columns = AVG:SLG,decimals = 3) %>%
376
+ fmt_percent(columns = ends_with("%")) %>%
377
+ sub_missing() %>%
378
+ #gt_theme_savant() %>%
379
+ opt_interactive(
380
+ use_compact_mode = TRUE,
381
+ use_pagination = FALSE
382
+ )
383
+ })
384
+ output$SideFilter <- render_gt({
385
+ test1 <- test %>% filter(Pitcher == input$player) %>% group_by(BatterSide) %>%
386
+ summarise(
387
+ Pitches = n(),
388
+ #BBE = sum(BBE,na.rm = TRUE),
389
+ "Whiff%" = mean(Whiff,na.rm = TRUE),
390
+ "CSW%" = mean(CSW,na.rm = TRUE),
391
+ "Zone%" = mean(Zone,na.rm = TRUE),
392
+ "ZCon%" = mean(Contact[Zone == TRUE & Swing == TRUE],na.rm = TRUE),
393
+ "ZSwing%" = mean(Swing[Zone == TRUE],na.rm = TRUE),
394
+ "OCon%" = mean(Contact[Zone == FALSE & Swing == TRUE],na.rm = TRUE),
395
+ "OSwing%" = mean(Swing[Zone == FALSE],na.rm = TRUE),
396
+ "Avg EV" = mean(ExitSpeed[BBE == TRUE],na.rm = TRUE),
397
+ "EV90" = quantile(ExitSpeed[BBE == TRUE],.9,na.rm = TRUE),
398
+ "Max EV" = max(ExitSpeed[BBE == TRUE],na.rm = TRUE),
399
+ "Max EV" = ifelse(is.infinite(`Max EV`),NA,`Max EV`),
400
+ "GB%" = mean(GB[BBE == TRUE],na.rm = TRUE),
401
+ "LD%" = mean(LD[BBE == TRUE],na.rm = TRUE),
402
+ "FB%" = mean(FB[BBE == TRUE],na.rm = TRUE),
403
+ "AVG" = round(sum(Hit,na.rm = TRUE) / sum(AB,na.rm = TRUE),digits = 3),
404
+ "OBP" = round((sum(Hit,na.rm = TRUE) + sum(Walk,na.rm = TRUE) + sum(HBP,na.rm = TRUE))/
405
+ sum(PA,na.rm = TRUE),digits = 3),
406
+ "SLG" = (round(sum(Single,na.rm = TRUE) + sum(Double,na.rm = TRUE) * 2 +
407
+ sum(Triple,na.rm = TRUE) * 3 + sum(HR,na.rm = TRUE)))/sum(AB,na.rm = TRUE))%>%
408
+ ungroup()
409
+ test2 <- test %>% mutate(BatterSide = "Both") %>%filter(Pitcher == "Beam, Drew") %>% group_by(BatterSide) %>%
410
+ summarise(
411
+ Pitches = n(),
412
+ #BBE = sum(BBE,na.rm = TRUE),
413
+ "Whiff%" = mean(Whiff,na.rm = TRUE),
414
+ "CSW%" = mean(CSW,na.rm = TRUE),
415
+ "Zone%" = mean(Zone,na.rm = TRUE),
416
+ "ZCon%" = mean(Contact[Zone == TRUE & Swing == TRUE],na.rm = TRUE),
417
+ "ZSwing%" = mean(Swing[Zone == TRUE],na.rm = TRUE),
418
+ "OCon%" = mean(Contact[Zone == FALSE & Swing == TRUE],na.rm = TRUE),
419
+ "OSwing%" = mean(Swing[Zone == FALSE],na.rm = TRUE),
420
+ "Avg EV" = mean(ExitSpeed[BBE == TRUE],na.rm = TRUE),
421
+ "EV90" = quantile(ExitSpeed[BBE == TRUE],.9,na.rm = TRUE),
422
+ "Max EV" = max(ExitSpeed[BBE == TRUE],na.rm = TRUE),
423
+ "Max EV" = ifelse(is.infinite(`Max EV`),NA,`Max EV`),
424
+ "GB%" = mean(GB[BBE == TRUE],na.rm = TRUE),
425
+ "LD%" = mean(LD[BBE == TRUE],na.rm = TRUE),
426
+ "FB%" = mean(FB[BBE == TRUE],na.rm = TRUE),
427
+ "AVG" = round(sum(Hit,na.rm = TRUE) / sum(AB,na.rm = TRUE),digits = 3),
428
+ "OBP" = round((sum(Hit,na.rm = TRUE) + sum(Walk,na.rm = TRUE) + sum(HBP,na.rm = TRUE))/
429
+ sum(PA,na.rm = TRUE),digits = 3),
430
+ "SLG" = (round(sum(Single,na.rm = TRUE) + sum(Double,na.rm = TRUE) * 2 +
431
+ sum(Triple,na.rm = TRUE) * 3 + sum(HR,na.rm = TRUE)))/sum(AB,na.rm = TRUE))%>%
432
+ ungroup()
433
+ test <- rbind(test1,test2)
434
+ test %>%
435
+ gt() %>%
436
+ gt_theme_tim() %>%
437
+ fmt_number(columns = `Avg EV`:`Max EV`,decimals = 1) %>%
438
+ cols_width(BatterSide:Pitches ~ px(70),
439
+ everything() ~ px(85)) %>%
440
+ cols_align(align = "center") %>%
441
+ cols_label(BatterSide = "Side") %>%
442
+ fmt_number(columns = AVG:SLG,decimals = 3) %>%
443
+ fmt_percent(columns = ends_with("%")) %>%
444
+ sub_missing() %>%
445
+ #gt_theme_savant() %>%
446
+ opt_interactive(
447
+ use_compact_mode = TRUE,
448
+ use_pagination = FALSE
449
+ )
450
+
451
+ })
452
+ output$slashline <- render_gt({
453
+ test <- test %>% filter(Pitcher == input$player) %>%
454
+ summarise(
455
+ Pitches = n(),
456
+ `1B` = sum(Single,na.rm = TRUE),
457
+ `2B` = sum(Double,na.rm = TRUE),
458
+ `3B` = sum(Triple,na.rm = TRUE),
459
+ HR = sum(HR,na.rm = TRUE),
460
+ SO = sum(Strikeout,na.rm = TRUE),
461
+ BB = sum(Walk,na.rm = TRUE),
462
+ Whiffs = sum(Whiff,na.rm = TRUE),
463
+ `Hard Hits` = sum(HardHit,na.rm = TRUE)
464
+ )%>%
465
+ ungroup()%>%
466
+ gt() %>%
467
+ gt_theme_tim() %>%
468
+ cols_align(align = "center") %>%
469
+ # gt_theme_savant() %>%
470
+ opt_interactive(
471
+ use_compact_mode = TRUE,
472
+ use_pagination = FALSE
473
+ )
474
+ })
475
+ }
476
+
477
+ # Run the application
478
+ shinyApp(ui = ui, server = server)