knitr::opts_chunk$set(echo = TRUE, message = FALSE, warning = FALSE)
library(readxl)
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(ggplot2)
library(knitr)

# Load the data
data <- read_excel("C:\\Users\\Franco Castagliuolo\\OneDrive - Bentley University\\Valley 75.xlsx")
# Filter the data for the pitcher Brandon Adams
Brandon_Adams_data <- data %>%
  filter(Pitcher == "Adams, Brandon")

# Create a detailed table for each pitch
detailed_pitch_table <- Brandon_Adams_data %>%
  select(AutoPitchType, RelSpeed, SpinRate, SpinAxis, HorzBreak, InducedVertBreak, PitchCall, RelHeight, RelSide, Extension) %>%
  rename(
    ReleaseSpeed = RelSpeed,
    Tilt = SpinAxis,
    HorizontalBreak = HorzBreak,
    InducedVerticalBreak = InducedVertBreak,
    ReleaseHeight = RelHeight,
    ReleaseSide = RelSide
  ) %>%
  mutate(
    ReleaseSpeed = round(ReleaseSpeed, 2),
    SpinRate = round(SpinRate, 2),
    Tilt = round(Tilt, 2),
    HorizontalBreak = round(HorizontalBreak, 2),
    InducedVerticalBreak = round(InducedVerticalBreak, 2),
    ReleaseHeight = round(ReleaseHeight, 2),
    ReleaseSide = round(ReleaseSide, 2),
    Extension = round(Extension, 2),
    ClockTilt = round((Tilt / 30) %% 12, 1) # Interpret Tilt as clock face
  )

# Display the detailed table
knitr::kable(detailed_pitch_table, caption = "Detailed Pitch Table for Brandon Adams")
Detailed Pitch Table for Brandon Adams
AutoPitchType ReleaseSpeed SpinRate Tilt HorizontalBreak InducedVerticalBreak PitchCall ReleaseHeight ReleaseSide Extension ClockTilt
Four-Seam 89.59 2160.56 221.36 13.04 16.04 BallCalled 5.62 2.39 6.52 7.4
Four-Seam 89.64 2248.84 217.84 11.46 15.98 StrikeCalled 5.73 2.39 6.28 7.3
Slider 78.02 2347.15 100.34 -10.39 3.23 BallCalled 5.52 2.63 5.64 3.3
Four-Seam 90.96 2271.30 202.67 8.92 22.56 StrikeSwinging 5.69 2.17 6.20 6.8
Four-Seam 90.60 2179.99 196.73 6.28 22.10 BallCalled 5.73 2.30 6.20 6.6
Four-Seam 91.33 2172.29 199.31 6.71 20.27 StrikeSwinging 5.58 2.31 6.50 6.6
Four-Seam 90.61 2122.96 208.52 10.38 20.25 BallCalled 5.60 2.44 6.35 7.0
Four-Seam 89.96 2136.08 205.99 8.01 17.54 BallCalled 5.43 2.31 6.83 6.9
Four-Seam 90.62 2148.42 205.94 9.69 21.06 StrikeSwinging 5.52 2.35 6.23 6.9
Four-Seam 90.69 1938.23 216.35 12.71 18.35 BallCalled 5.49 2.35 6.60 7.2
Four-Seam 88.85 1939.09 215.77 11.29 16.68 BallCalled 5.53 2.27 8.23 7.2
Four-Seam 88.99 1988.47 215.28 11.58 17.38 BallCalled 5.61 2.20 6.56 7.2
Curveball 76.82 2280.29 59.88 -12.05 -5.62 StrikeCalled 5.37 2.57 5.84 2.0
Curveball 78.21 2335.66 58.67 -12.04 -6.01 BallCalled 5.47 2.48 5.63 2.0
Four-Seam 89.54 1957.60 211.02 10.16 17.96 StrikeSwinging 5.55 2.01 6.95 7.0
Four-Seam 90.10 1944.33 207.11 9.19 19.04 StrikeSwinging 5.56 2.24 6.56 6.9
Four-Seam 89.87 2168.07 212.14 11.46 19.39 FoulBallNotFieldable 5.64 2.19 6.36 7.1
Curveball 78.14 2268.93 68.53 -12.06 -3.46 InPlay 5.43 2.40 5.73 2.3
Four-Seam 89.86 2173.24 206.59 9.84 20.83 BallCalled 5.61 2.13 6.20 6.9
Slider 77.03 2389.74 76.31 -16.09 -2.47 StrikeCalled 5.36 2.49 5.68 2.5
Slider 78.32 2337.36 77.58 -13.10 -1.53 FoulBallNotFieldable 5.42 2.34 5.61 2.6
Four-Seam 90.02 2152.05 211.11 10.47 18.53 StrikeCalled 5.66 2.08 6.27 7.0
Slider 77.27 2277.70 89.84 -12.15 1.32 BallCalled 5.39 2.30 5.91 3.0
Four-Seam 88.69 2163.98 211.01 11.44 20.18 HitByPitch 5.60 2.18 6.73 7.0
Slider 78.13 2230.27 73.38 -8.35 -1.12 BallCalled 5.35 2.27 5.98 2.4
Four-Seam 88.60 2070.99 208.40 10.30 20.21 InPlay 5.56 2.16 6.64 6.9
Four-Seam 89.07 1876.92 208.95 9.07 17.46 FoulBallNotFieldable 5.57 2.17 6.83 7.0
Sinker 89.48 1949.27 230.37 15.63 14.11 StrikeSwinging 5.61 2.44 6.19 7.7
Four-Seam 89.76 2056.67 219.30 12.32 16.17 InPlay 5.61 2.37 6.19 7.3
# Calculate the total number of pitches
total_pitches <- nrow(detailed_pitch_table)

# Create a summary table
pitch_summary <- detailed_pitch_table %>%
  group_by(AutoPitchType) %>%
  summarise(
    TotalPitches = n(),
    Usage = sprintf("%.2f%%", n() / total_pitches * 100),
    Balls = sum(PitchCall == "BallCalled"),
    Strikes = sum(PitchCall != "BallCalled"), # Count everything not a ball as a strike
    BallPercentage = sprintf('%.2f%%', Balls / TotalPitches * 100),
    StrikePercentage = sprintf('%.2f%%', Strikes / TotalPitches * 100),
    AvgVelocity = round(mean(ReleaseSpeed, na.rm = TRUE), 2),
    AvgSpinRate = round(mean(SpinRate, na.rm = TRUE), 2),
    AvgInducedVertBreak = round(mean(InducedVerticalBreak, na.rm = TRUE), 2),
    AvgHorzBreak = round(mean(HorizontalBreak, na.rm = TRUE), 2),
    AvgTilt = round(mean(Tilt, na.rm = TRUE), 2),
    AvgClockTilt = round(mean(ClockTilt, na.rm = TRUE), 1), # Clock face interpretation
    AvgReleaseHeight = round(mean(ReleaseHeight, na.rm = TRUE), 2),
    AvgReleaseSide = round(mean(ReleaseSide, na.rm = TRUE), 2),
    AvgExtension = round(mean(Extension, na.rm = TRUE), 2)
  ) %>%
  select(AutoPitchType, Usage, everything())

# Display the total number of pitches
cat("Total number of pitches thrown: ", total_pitches, "\n")
## Total number of pitches thrown:  29
# Display the summary table
knitr::kable(pitch_summary, caption = "Summary Pitch Table for Brandon Adams")
Summary Pitch Table for Brandon Adams
AutoPitchType Usage TotalPitches Balls Strikes BallPercentage StrikePercentage AvgVelocity AvgSpinRate AvgInducedVertBreak AvgHorzBreak AvgTilt AvgClockTilt AvgReleaseHeight AvgReleaseSide AvgExtension
Curveball 10.34% 3 1 2 33.33% 66.67% 77.72 2294.96 -5.03 -12.05 62.36 2.1 5.42 2.48 5.73
Four-Seam 68.97% 20 8 12 40.00% 60.00% 89.87 2093.50 18.90 10.22 210.07 7.0 5.59 2.25 6.56
Sinker 3.45% 1 0 1 0.00% 100.00% 89.48 1949.27 14.11 15.63 230.37 7.7 5.61 2.44 6.19
Slider 17.24% 5 3 2 60.00% 40.00% 77.75 2316.44 -0.11 -12.02 83.49 2.8 5.41 2.41 5.76
# Calculate maximum fastball velocity
max_fb_velocity <- detailed_pitch_table %>%
  filter(AutoPitchType %in% c("Four-Seam", "Two-Seam", "Sinker", "Cutter")) %>%
  summarise(MaxFBVelocity = max(ReleaseSpeed, na.rm = TRUE)) %>%
  pull(MaxFBVelocity)

# Display the maximum fastball velocity
cat("Brandon Adams maximum FB velocity: ", max_fb_velocity, "mph\n")
## Brandon Adams maximum FB velocity:  91.33 mph
# Prepare data for plotting pitch locations
pitch_location_data <- Brandon_Adams_data %>%
  select(AutoPitchType, PlateLocHeight, PlateLocSide, PitchCall) %>%
  rename(
    PitchHeight = PlateLocHeight,
    PitchSide = PlateLocSide
  ) %>%
  mutate(
    SwingTake = ifelse(PitchCall %in% c("StrikeSwinging", "FoulBallNonSwinging", "FoulBallFieldable", "FoulBallNotFieldable", "InPlay"), "Swing", "Take"),
    Chase = ifelse(SwingTake == "Swing" & (PitchSide < -0.75 | PitchSide > 0.75 | PitchHeight < 1.5 | PitchHeight > 3.5), "Chase", "Non-Chase")
  )

# Create the scatter plot with specified strike zone boxes
ggplot(pitch_location_data, aes(x = PitchSide, y = PitchHeight, color = SwingTake, shape = Chase)) +
  geom_point(size = 3) +
  geom_rect(aes(xmin = -0.5, xmax = 0.5, ymin = 1.75, ymax = 3.25), fill = NA, color = "red", linetype = "solid", size = 1) + 
  geom_rect(aes(xmin = -0.75, xmax = 0.75, ymin = 1.5, ymax = 3.5), fill = NA, color = "black", linetype = "solid", size = 1) + 
  geom_rect(aes(xmin = -1.25, xmax = 1.25, ymin = 1.25, ymax = 3.75), fill = NA, color = "gray", linetype = "solid", size = 1) +
  scale_x_continuous(limits = c(-2, 2)) +
  scale_y_continuous(limits = c(0, 5)) +
  coord_fixed(ratio = 1) +
  labs(title = "Pitch Locations for Brandon Adams",
       x = "Horizontal Location (feet)",
       y = "Vertical Location (feet)",
       color = "Swing/Take",
       shape = "Chase") +
  facet_wrap(~ AutoPitchType) +
  theme_minimal() +
  theme(
    legend.position = "right",
    panel.grid.major = element_line(color = "grey80"),
    panel.grid.minor = element_line(color = "grey90"),
    axis.text = element_text(color = "black"),
    axis.title = element_text(color = "black"),
    plot.title = element_text(color = "black"),
    legend.background = element_rect(fill = "white", color = NA),
    legend.key = element_rect(fill = "white", color = NA),
    legend.text = element_text(color = "black"),
    legend.title = element_text(color = "black")
  )

# Create the scatter plot for horizontal and vertical breaks
ggplot(detailed_pitch_table, aes(x = HorizontalBreak, y = InducedVerticalBreak, color = AutoPitchType)) +
  geom_point(size = 3) + # Increase point size
  scale_x_continuous(limits = c(-25, 25)) +  # Set horizontal limits to +/- 25 inches
  scale_y_continuous(limits = c(-25, 25)) +  # Set vertical limits to +/- 25 inches
  labs(title = paste("Pitch Movement for", unique(detailed_pitch_table$AutoPitchType)),
       x = "Horizontal Break (inches)",
       y = "Induced Vertical Break (inches)",
       color = "Pitch Type") +
  theme_minimal() +
  theme(
    legend.position = "right",
    panel.grid.major = element_line(color = "grey80"),
    panel.grid.minor = element_line(color = "grey90"),
    axis.text = element_text(color = "black"),
    axis.title = element_text(color = "black"),
    plot.title = element_text(color = "black"),
    legend.background = element_rect(fill = "white", color = NA),
    legend.key = element_rect(fill = "white", color = NA),
    legend.text = element_text(color = "black"),
    legend.title = element_text(color = "black")
  )