Skip to content

Instantly share code, notes, and snippets.

@bayesball
Created July 28, 2024 14:55
Show Gist options
  • Save bayesball/48e93878beeae97942419880145925cb to your computer and use it in GitHub Desktop.
Save bayesball/48e93878beeae97942419880145925cb to your computer and use it in GitHub Desktop.
R function for fitting a normal mixture model to exit velocities for balls in play for a specific baseball hitter.
fit_norm_mix_model <- function(pname, statcast){
require(dplyr)
require(LearnBayes)
library(magrittr)
logpost <- function(theta, y){
mu1 <- theta[1]
sigma1 <- exp(theta[2])
mu2 <- theta[3]
sigma2 <- exp(theta[4])
p <- exp(theta[5]) / (1 + exp(theta[5]))
sum(log(p * dnorm(y, mu1, sigma1) +
(1 - p) * dnorm(y, mu2, sigma2)))
}
invlogit <- function(y){
exp(y) / (1 + exp(y))
}
statcast |>
filter(type == "X",
player_name == pname) |>
filter(is.na(launch_speed) == FALSE) |>
pull(launch_speed) -> y_AB
y1 <- y_AB[y_AB < median(y_AB)]
y2 <- y_AB[y_AB > median(y_AB)]
theta0 <- c(mean(y1), log(sd(y1)),
mean(y2), log(sd(y2)), 0)
laplace(logpost, theta0, y_AB) |>
extract2(1) -> Mode
data.frame(player_name = pname,
mu1 = Mode[1], log_sd1 = Mode[2],
mu2 = Mode[3], log_sd2 = Mode[4],
logit_p = Mode[5]) |>
mutate(sd1 = exp(log_sd1),
sd2 = exp(log_sd2),
p = invlogit(logit_p)) |>
select(player_name, mu1, sd1, mu2, sd2, p)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment