TimStats's picture
Update app.R
2fdd1b2 verified
Raw
History Blame
5.46 kB
library(shiny)
library(dplyr)
library(data.table)
library(xgboost)
library(caret)
library(shinythemes)
calculate_timstuff <- function(data, pitch_type) {
data_matrix <- as.matrix(data)
if (pitch_type == "Offspeed") {
mod <- xgb.load('Off.model')
prediction <- predict(mod, data_matrix)
timstuff <- (50 - (prediction - -0.002239657) / 0.01043216 * 10)
} else {
mod <- xgb.load('FB.model')
prediction <- predict(mod, data_matrix)
timstuff <- (50 - (prediction - -0.0011801) / 0.007989927 * 10)
}
return(timstuff)
}
ui <- fluidPage(
theme = shinytheme("flatly"),
# Application title
titlePanel("TimStuff Fastball/Offspeed Calculator"),
# Sidebar with inputs
sidebarLayout(
sidebarPanel(
width = 4,
radioButtons("pitch", "Pitch Type", choices = c("Fastball", "Offspeed"), inline = TRUE),
radioButtons("phand", "Hand", choices = c("R", "L"), inline = TRUE),
numericInput("velo", "Velocity (mph)", value = 90, min = 70, max = 110, step = 1),
numericInput("ivb", "Induced Vertical Break (in)", value = 16, min = -20, max = 30, step = 0.1),
numericInput("hb", "Horizontal Break (in)", value = 6, min = -20, max = 20, step = 0.1),
numericInput("spinrate", "Spin Rate (rpm)", value = 2300, min = 1000, max = 3500, step = 10),
numericInput("ext", "Extension (ft)", value = 6, min = 5, max = 8, step = 0.1),
numericInput("spinaxisdiff", "Spin Axis Difference (°)", value = 0, min = -180, max = 180, step = 1),
numericInput("x0", "Horizontal Release Point (ft)", value = 0, min = -5, max = 5, step = 0.1),
numericInput("z0", "Vertical Release Point (ft)", value = 5, min = 3, max = 8, step = 0.1),
selectInput("feature_to_vary", "Select Feature to Vary:",
choices = c("Velocity" = "start_speed",
"Induced Vertical Break" = "IVB",
"Horizontal Break" = "HB",
"Spin Rate" = "spin_rate",
"Extension" = "EAA",
"Spin Axis Difference" = "SADiff",
"Horizontal Release Point" = "x0",
"Vertical Release Point" = "z0"))
),
# Main panel with output
mainPanel(
width = 8,
wellPanel(
h3("Results"),
verbatimTextOutput("stuff"),
plotOutput("feature_impact", height = "400px") # Placeholder for future visualization
)
)
)
)
server <- function(input, output) {
observeEvent(input$pitch, {
output$stuff <- renderText({
data <- data.frame(
start_speed = input$velo,
IVB = input$ivb,
HB = ifelse(input$phand == "L", -input$hb, input$hb),
EAA = input$ext / 6.3,
x0 = ifelse(input$phand == "L", -input$x0, input$x0),
z0 = input$z0,
spin_rate = input$spinrate,
SADiff = input$spinaxisdiff
)
data <- as.matrix(data)
if (input$pitch == "Offspeed") {
mod <- xgb.load('Off.model')
prediction <- predict(mod, data)
TimStuff <- (50 - (prediction - -0.002239657) / 0.01043216 * 10)
} else {
mod <- xgb.load('FB.model')
prediction <- predict(mod, data)
TimStuff <- (50 - (prediction - -0.0011801) / 0.007989927 * 10)
}
paste("TimStuff:", round(TimStuff, 2), "\n20-80 Scale, 50 is Average, 1 SD is 10")
})
# Add this new reactive expression
# Add this new reactive expression
feature_range <- reactive({
ranges <- list(
start_speed = c(70, 110),
IVB = c(-20, 30),
HB = c(-20, 20),
spin_rate = c(1000, 3500),
EAA = c(5/6.3, 8/6.3),
SADiff = c(-180, 180),
x0 = c(-5, 5),
z0 = c(3, 8)
)
ranges[[input$feature_to_vary]]
})
# Update the feature_impact plot
output$feature_impact <- renderPlot({
# Create base data frame with current inputs
base_data <- data.frame(
start_speed = input$velo,
IVB = input$ivb,
HB = ifelse(input$phand == "L", -input$hb, input$hb),
EAA = input$ext / 6.3,
x0 = ifelse(input$phand == "L", -input$x0, input$x0),
z0 = input$z0,
spin_rate = input$spinrate,
SADiff = input$spinaxisdiff
)
# Generate sequence for the selected feature
feature_seq <- seq(feature_range()[1], feature_range()[2], length.out = 100)
# Calculate TimStuff for the sequence
varied_data <- do.call(rbind, replicate(100, base_data, simplify = FALSE))
varied_data[[input$feature_to_vary]] <- feature_seq
timstuff <- calculate_timstuff(varied_data, input$pitch)
# Create plot data
plot_data <- data.frame(
Feature = names(base_data)[which(names(base_data) == input$feature_to_vary)],
Value = feature_seq,
TimStuff = timstuff
)
# Create plot
ggplot(plot_data, aes(x = Value, y = TimStuff)) +
geom_line(color = "blue", size = 1) +
geom_point(aes(x = base_data[[input$feature_to_vary]],
y = calculate_timstuff(base_data, input$pitch)),
color = "red", size = 3) +
theme_minimal() +
ylim(0,100) +
labs(title = paste("Impact of", input$feature_to_vary, "on TimStuff"),
x = input$feature_to_vary, y = "TimStuff") +
theme(text = element_text(size = 14))
})
})
}
# Run the application
shinyApp(ui = ui, server = server)