Skip to content

Instantly share code, notes, and snippets.

@bayesball
Last active March 31, 2018 13:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bayesball/71f5839529cfa1589f41f4edb938e349 to your computer and use it in GitHub Desktop.
Save bayesball/71f5839529cfa1589f41f4edb938e349 to your computer and use it in GitHub Desktop.
R code to find optimal launch angles from Statcast data
# read in tidyveres package
library(tidyverse)
# read in the Statcast data for the 2017 season
# the file statcast2017.csv can be downloaded from the folder
# http://www-math.bgsu.edu/~albert/statcast/
sc <- read_csv("statcast2017.csv")
# only consider balls put in play
sc_ip <- filter(sc, type == "X")
# exploring relationship between launch angle,
# exit velocity, and hit/out
# first remove home runs and focus on
# P(hit | in play and not home run)
# Also remove sac hits and sac flies
# define the hit variable
sc_ip %>% filter(events != "home_run",
! (events %in%
c("sac_bunt", "sac_fly",
"sac_fly_double_play"))) %>%
mutate(hit = ifelse(events %in%
c("single", "double", "triple", "home_run"),
1, 0)) -> sc_ip2
# only look at balls hit in the air and
# define a factor variable Hit
sc_ip3 <- filter(sc_ip2, launch_angle > 0)
sc_ip3$Hit <- as.factor(sc_ip3$hit)
# scatterplot of launch angles and exit velocities
ggplot(sc_ip3,
aes(launch_angle, launch_speed, color=Hit)) +
geom_point(size = 0.7, alpha = 0.1) +
ylim(25, 125) +
ggtitle("Scatterplot of Launch Angle
and Launch Speed for Balls in Air") +
theme(
plot.title = element_text(
colour = "blue",
size = 16,
hjust = 0.5
)
) +
xlim(0, 40) + ylim(50, 115)
# focus on hits with a specific velocity
# look at the pattern of binned data
# write a function to do this for any speed
efit_model2 <- function(ev, width=1, delta=1){
# width is for the binning of launch angle
# delta determines blur of launch speed
# only considering launch angles in (0, 30)
d <- filter(sc_ip3,
launch_speed > ev - delta / 2,
launch_speed < ev + delta / 2,
launch_angle < 30)
d$LA <- cut(d$launch_angle,
breaks = seq(0, 30, by=width))
d %>%
group_by(LA) %>%
summarize(N = n(),
H = sum(hit),
Probability = H / N) -> S
S %>% mutate(Mid = seq(0, 30 - width, by=width) +
width / 2,
launch_speed = ev)
}
# run this function for a collection of exit velocities
map_df(c(75, 80, 85, 90),
efit_model2, width=2, delta = 2) -> out
out$Launch_Speed = paste("Launch Speed =",
out$launch_speed, "mph")
write_csv(out, "plotdata.csv")
map_df(c(95, 100, 105),
efit_model2, width=2, delta = 2) -> out
out$Launch_Speed = paste("Launch Speed =",
out$launch_speed, "mph")
write_csv(out, "plotdata2.csv")
##### graphing part
d <- read_csv("plotdata.csv")
d2 <- read_csv("plotdata2.csv")
ggplot(d, aes(Mid, Probability)) +
geom_point(color="red") +
geom_smooth(method="loess") +
facet_wrap(~ Launch_Speed, ncol=2) +
xlab("Launch Angle (degrees)") +
ylab("Probability(Hit)") +
theme(strip.text.x = element_text(size=16, color="red"),
text = element_text(size=16))
ggplot(d2, aes(Mid, Probability)) +
geom_point(color="red") +
geom_smooth(method="loess") +
facet_wrap(~ Launch_Speed, ncol=2) +
xlab("Launch Angle (degrees)") +
ylab("Probability(Hit)") +
theme(strip.text.x = element_text(size=14, color="red"),
text = element_text(size=16))
# graph the optimal angles
df <- data.frame(Launch_Speed = seq(75, 105, by = 5),
Optimal_Launch_Angle = c(20, 17,
15, 13, 12, 11, 10 ))
ggplot(df, aes(Launch_Speed,
Optimal_Launch_Angle)) +
geom_point(size = 3, color="red") +
ggtitle("Optimal Launch Angle") +
theme(
plot.title = element_text(
colour = "blue",
size = 18,
hjust = 0.5
)
) +
theme(strip.text.x = element_text(size=16, color="red"),
text = element_text(size=16))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment