# Filter the data for the pitcher Jaun
Jaun_data <- Sanford69 %>%
filter(Pitcher == "Jaun, William")
# Create a detailed table for each pitch
detailed_pitch_table <- Jaun_data %>%
select(AutoPitchType, RelSpeed, SpinRate, SpinAxis, HorzBreak, InducedVertBreak, PitchCall, RelHeight, RelSide) %>%
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),
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 Jaun")
Detailed Pitch Table for Jaun
Sinker |
87.29 |
2211.12 |
135.08 |
-13.83 |
15.16 |
BallCalled |
5.73 |
-2.16 |
4.5 |
Sinker |
87.41 |
2229.04 |
137.89 |
-15.23 |
18.15 |
BallCalled |
5.91 |
-2.08 |
4.6 |
Sinker |
86.08 |
2214.43 |
143.09 |
-13.52 |
19.38 |
StrikeCalled |
5.89 |
-1.92 |
4.8 |
Four-Seam |
87.62 |
2227.62 |
141.36 |
-13.17 |
17.73 |
FoulBallNotFieldable |
5.88 |
-1.95 |
4.7 |
Slider |
73.60 |
2344.69 |
273.47 |
27.28 |
-0.03 |
StrikeSwinging |
6.10 |
-1.09 |
9.1 |
NA |
86.22 |
2057.77 |
NA |
NA |
NA |
BallCalled |
6.13 |
-1.98 |
NA |
Sinker |
85.63 |
2168.17 |
135.25 |
-17.03 |
18.45 |
FoulBallNotFieldable |
5.87 |
-1.95 |
4.5 |
NA |
87.97 |
2201.83 |
NA |
NA |
NA |
BallCalled |
6.08 |
-2.03 |
NA |
NA |
86.33 |
2137.36 |
NA |
NA |
NA |
BallCalled |
6.14 |
-1.78 |
NA |
Sinker |
86.07 |
2124.98 |
134.27 |
-12.38 |
13.49 |
FoulBallNotFieldable |
5.72 |
-2.00 |
4.5 |
Curveball |
74.07 |
2389.51 |
305.27 |
15.24 |
-8.96 |
StrikeCalled |
6.08 |
-1.61 |
10.2 |
Four-Seam |
88.10 |
2226.36 |
139.29 |
-12.24 |
15.43 |
BallCalled |
5.78 |
-2.02 |
4.6 |
Sinker |
87.79 |
2204.37 |
128.49 |
-16.59 |
14.44 |
BallCalled |
5.77 |
-2.03 |
4.3 |
NA |
72.08 |
2256.52 |
NA |
NA |
NA |
BallCalled |
6.18 |
-1.42 |
NA |
Changeup |
84.50 |
2100.40 |
129.14 |
-18.19 |
16.18 |
StrikeCalled |
5.93 |
-1.69 |
4.3 |
Four-Seam |
87.34 |
2167.31 |
144.39 |
-11.62 |
17.50 |
BallCalled |
5.83 |
-1.91 |
4.8 |
Four-Seam |
86.21 |
2121.50 |
149.67 |
-9.57 |
17.57 |
BallCalled |
5.82 |
-1.82 |
5.0 |
Four-Seam |
87.09 |
2118.61 |
149.59 |
-10.76 |
19.60 |
InPlay |
5.93 |
-1.81 |
5.0 |
NA |
88.14 |
2234.73 |
NA |
NA |
NA |
BallCalled |
6.23 |
-1.94 |
NA |
Sinker |
85.62 |
2147.65 |
130.94 |
-13.50 |
12.96 |
StrikeCalled |
5.81 |
-1.98 |
4.4 |
NA |
71.54 |
2257.18 |
NA |
NA |
NA |
BallCalled |
6.26 |
-1.54 |
NA |
Four-Seam |
87.39 |
2209.04 |
151.71 |
-9.09 |
18.11 |
FoulBallNotFieldable |
5.89 |
-1.87 |
5.1 |
NA |
75.87 |
2481.18 |
NA |
NA |
NA |
StrikeCalled |
6.31 |
-1.49 |
NA |
Changeup |
84.71 |
2071.83 |
140.74 |
-12.11 |
16.11 |
FoulBallNotFieldable |
5.97 |
-1.79 |
4.7 |
Changeup |
76.34 |
1552.12 |
100.54 |
-20.87 |
5.38 |
BallCalled |
5.85 |
-1.87 |
3.4 |
Changeup |
84.83 |
1994.25 |
140.44 |
-13.51 |
17.59 |
StrikeCalled |
5.86 |
-1.89 |
4.7 |
NA |
77.31 |
1403.06 |
NA |
NA |
NA |
InPlay |
6.02 |
-1.72 |
NA |
NA |
71.28 |
2287.95 |
NA |
NA |
NA |
StrikeCalled |
6.30 |
-1.52 |
NA |
Changeup |
86.31 |
2116.78 |
105.29 |
-27.50 |
8.74 |
BallCalled |
5.42 |
-3.22 |
3.5 |
Changeup |
76.74 |
1348.79 |
154.58 |
-7.03 |
16.29 |
StrikeCalled |
5.81 |
-1.83 |
5.2 |
Curveball |
72.63 |
2409.13 |
298.13 |
15.66 |
-6.75 |
BallCalled |
6.21 |
-1.30 |
9.9 |
NA |
85.79 |
2148.86 |
NA |
NA |
NA |
BallCalled |
6.21 |
-1.70 |
NA |
Sinker |
86.67 |
2083.50 |
129.78 |
-14.04 |
12.99 |
FoulBallNotFieldable |
6.00 |
-1.50 |
4.3 |
Curveball |
71.79 |
2379.98 |
317.28 |
14.27 |
-13.66 |
InPlay |
6.07 |
-1.33 |
10.6 |
NA |
70.04 |
2226.24 |
NA |
NA |
NA |
BallCalled |
6.45 |
-1.29 |
NA |
NA |
85.66 |
2026.97 |
NA |
NA |
NA |
BallCalled |
6.18 |
-1.62 |
NA |
Sinker |
85.44 |
2118.57 |
141.46 |
-11.82 |
15.97 |
StrikeCalled |
5.90 |
-1.82 |
4.7 |
Changeup |
76.20 |
1388.56 |
111.15 |
-16.25 |
7.73 |
BallCalled |
5.72 |
-2.00 |
3.7 |
Changeup |
84.66 |
1985.58 |
140.26 |
-13.97 |
17.99 |
BallCalled |
6.02 |
-1.88 |
4.7 |
Changeup |
85.41 |
2089.42 |
126.06 |
-13.84 |
11.23 |
StrikeCalled |
5.77 |
-1.98 |
4.2 |
Changeup |
76.36 |
1480.13 |
122.24 |
-14.68 |
10.76 |
InPlay |
5.93 |
-1.88 |
4.1 |
# Create a summary table
pitch_summary <- detailed_pitch_table %>%
group_by(AutoPitchType) %>%
summarise(
TotalPitches = n(),
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)
)
# Display the summary table
knitr::kable(pitch_summary, caption = "Summary Pitch Table for Jaun")
Summary Pitch Table for Jaun
Changeup |
10 |
4 |
6 |
40.00% |
60.00% |
81.61 |
1812.79 |
12.80 |
-15.80 |
127.04 |
4.2 |
5.83 |
-2.00 |
Curveball |
3 |
1 |
2 |
33.33% |
66.67% |
72.83 |
2392.87 |
-9.79 |
15.06 |
306.89 |
10.2 |
6.12 |
-1.41 |
Four-Seam |
6 |
3 |
3 |
50.00% |
50.00% |
87.29 |
2178.41 |
17.66 |
-11.07 |
146.00 |
4.9 |
5.86 |
-1.90 |
Sinker |
9 |
3 |
6 |
33.33% |
66.67% |
86.44 |
2166.87 |
15.67 |
-14.22 |
135.14 |
4.5 |
5.84 |
-1.94 |
Slider |
1 |
0 |
1 |
0.00% |
100.00% |
73.60 |
2344.69 |
-0.03 |
27.28 |
273.47 |
9.1 |
6.10 |
-1.09 |
NA |
12 |
9 |
3 |
75.00% |
25.00% |
79.85 |
2143.30 |
NaN |
NaN |
NaN |
NaN |
6.21 |
-1.67 |
# Prepare data for plotting pitch locations
pitch_location_data <- Jaun_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) + # Increase point size
geom_rect(aes(xmin = -0.5, xmax = 0.5, ymin = 1.75, ymax = 3.25), fill = NA, color = "red", linetype = "solid", size = 1) + # Red box
geom_rect(aes(xmin = -0.75, xmax = 0.75, ymin = 1.5, ymax = 3.5), fill = NA, color = "black", linetype = "solid", size = 1) + # Black box
geom_rect(aes(xmin = -1.25, xmax = 1.25, ymin = 1.25, ymax = 3.75), fill = NA, color = "gray", linetype = "solid", size = 1) + # Gray box
scale_x_continuous(limits = c(-2, 2)) +
scale_y_continuous(limits = c(0, 5)) +
coord_fixed(ratio = 1) + # Adjust ratio to shrink vertical distance
labs(title = "Pitch Locations for Jaun",
x = "Horizontal Location (feet)",
y = "Vertical Location (feet)",
color = "Swing/Take",
shape = "Chase") +
facet_wrap(~ AutoPitchType) + # Create individual graphs for each pitch type
geom_text(aes(x = -1.75, y = 5, label = "RHH"), color = "black", size = 3, hjust = 0) + # Label for RHH
geom_text(aes(x = 1.75, y = 5, label = "LHH"), color = "black", size = 3, hjust = 1) + # Label for LHH
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
labs(title = "Pitch Movement for Jaun",
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")
)
