Projections using Hypertuned model through XGboost
All data is from FanGraphs. I have no affiliation with FanGraphs, but please consider contributing to their website if you found this project informative.
This project is designed to showcase how Using a Percentile Based Worth System values Fantasy Baseball Players through a Inning Pitched (IP) weighted projection
The Categories used for prediction valuation are year-end rankings for the following metrics:
First we need to load the packages that R needs to run the analysis
library(sqldf) #SQL in R
library(skimr) #Summaries and useful for removing low % data
library(ggplot2) #Plotting Functions
library(plyr) #slightly deprecated data cleaning
library(dplyr) #slightly updated data cleaning
library(tidyverse) #tidyverse data cleaning universe
library(caret) #wrapper for creating, tuning and validating models
library(xgboost) #package for creating regression tree model
library(vtreat) # useful package for treating data before modeling
library(Matrix) #creating matricies for xgboost
library(mgcv)
library(moments) #for measuring skewness
library(data.table) #alternative to dplyr we use to create lags
library(pdp) #partial dependence graphs
library(vip) #variable importance
library(grid) #put multiple plots on one grid
library(gridExtra) #additional grid functionality
library(janitor) #one function used to clean transposed data set
library(ggpubr) #for qq plot
library(owmr) #Removing Prefixes
library(kableExtra) # formatting HTML Tables
library(formattable) # formatting HTML TablesThe # comments generally explain what additional functionality each library adds to R
All data is downloaded from Fan Graphs from this location. The data is also available on my Github here. There are player level and team data sets
#data read-in
pitcher_data <- read_csv("FanGraphs Leaderboard_Pitching20IP.csv")#Team datasets
FDG_Team = read_csv("FanGraphs Leaderboard_Team.csv")#Create a prefix for all team stats that starts with T_
FDG_Team2 <- FDG_Team %>%
rename_with( ~ paste0("T_", .x))str give information about an object, while
skim provides a customizable summary
#Output not shown for space
#str(FDG_Team2)
skim(FDG_Team2) %>%
tibble::as_tibble() #Remove this option for a normal HTML tableskim let’s us see how the data was imported into R.
Documentation can be found here
#Full Dataset dimensions
skimr::skim(pitcher_data) %>%
tibble::as_tibble() %>% #Remove this option for a normal HTML table
select(skim_type,skim_variable,complete_rate) %>%
filter(complete_rate >0.30) #250 Variables
#skim_type - character or numeric
#skim_variable - name of variable
#complete_rate - % of data that is not missing
#filter - only keep variables that have 30% of data populatedAdditionally let’s look at how variables vary by year to see if there are any discrepancies there
#It looks like one year, there were fewer games played, and there is a clear drop off in home runs
pitcher_data_dist =
pitcher_data %>%
group_by(Season) %>%
summarize (Max_Games = max(G),
Avg_W= mean(W)
)
pitcher_data_dist
#Plot Win Data by Year
ggplot(pitcher_data_dist, aes(Season, Avg_W)) +
geom_col()+
ggtitle("Average Wins by Year")+
theme(plot.title = element_text(hjust = 0.5,size = 22,color ="steel blue"))What are some issues with the data?
Many of Variables, such as K%, are being read in as characters
There is spotty data coverage in some of the variables (~Variables have less than 30% Coverage)
2020 Data only includes 60 games worth of data
Team Data needs to be appended to pitcher Data by Team Name
There are several ways to do this, we will identify the variables we
want to change that are mis-identified. parse_number can be
used to pull numbers from these variables. Additional ways to tackle
this can be found here.
#Select Column names that are characters but not Team or Name, These should be percentages
pitcher_data_chars_to_convert <- pitcher_data %>%
select_if(is.character)%>% select(-Team,-Name) %>%
mutate_all (function(x) as.numeric(readr::parse_number(x))/100)
#Note : There are additional ways to do this, this is just one solution
#We can exclude the variables we converted and reintroduce them
pitcher_data_num <- pitcher_data %>% select(-colnames(pitcher_data_chars_to_convert))
pitcher_data2 = cbind(pitcher_data_num,pitcher_data_chars_to_convert) %>%
select (colnames(pitcher_data)) %>% #preserve original order
dplyr::rename(flyball_perc = `FB%...50`,fastball_perc = `FB%...74`) #rename two ambiguous columns
skim(pitcher_data2) %>%
as_tibble() %>%
group_by(skim_type) %>%
count()
#Logical variables are R's best guess, in our case they are all NA's and will be removed at a later stepThe same can be done for the Team Data that is loaded
#Select Column names that are characters but not Team or Name, These should be percentages
FDG_Team2_chars_to_convert <- FDG_Team2 %>%
select_if(is.character)%>% select(-T_Team) %>%
mutate_all (function(x) as.numeric(readr::parse_number(x))/100)
#Keep in mind, parse number may make actual characters into numerical variables so carefully check your data before using
#We can exclude the variables we converted and reintroduce them
FDG_Team2_num <- FDG_Team2 %>% select(-colnames(FDG_Team2_chars_to_convert))
FDG_Team3 = cbind(FDG_Team2_num,FDG_Team2_chars_to_convert) %>%
select (colnames(FDG_Team2)) %>% #preserve original order
dplyr::rename(T_flyball_perc = `T_FB%...45`,T_fastball_perc = `T_FB%...72`) #rename two ambiguous columns
skim(FDG_Team3) %>%
as_tibble() %>%
group_by(skim_type) %>%
count()I choose 30% coverage of data necessary but this can be adjusted up
or down. This will also get rid of columns that are all
NA.
# Keep variables with enough values (Need 30% data coverage rate here)
Player_cols_to_keep =
skim(pitcher_data2) %>%
dplyr::select(skim_type, skim_variable, complete_rate) %>%
filter (complete_rate > 0.30)
#Transpose Rows to get column names as skim melts the data
Player_cols_to_keep_transpose = t(Player_cols_to_keep)
#extract the colnames we would like to keep
Player_cols_to_keep = colnames(janitor::row_to_names(Player_cols_to_keep_transpose,row_number = 2))
#Only keep the columns designated to have over 30% of their data populated or greater
pitcher_data3 = pitcher_data2 %>%
select(one_of(Player_cols_to_keep)) Repeat the process for Team Variables
Team_cols_to_keep =
skim(FDG_Team3) %>%
dplyr::select(skim_type, skim_variable, complete_rate) %>%
filter (complete_rate > 0.30)
#Transpose Rows to get column names as skim melts the data
Team_cols_to_keep_transpose = t(Team_cols_to_keep)
#extract the colnames we would like to keep
Team_cols_to_keep = colnames(janitor::row_to_names(Team_cols_to_keep_transpose,row_number = 2))
#Only keep the columns designated to have over 30% of their data populated or greater
FDG_Team4 = FDG_Team3 %>%
select(one_of(Team_cols_to_keep)) Some Variables will need to be normalized by Innings_Pitched (IP) if they aren’t a percentage already. Remaining Variables are percentages or indices so will not need to be transformed. The full data dictionary for these variables can be found on FanGraph’s website here. for pitching variables and here. for hitting variables.
pitcher_data4 = pitcher_data3 %>%
mutate( #create new variables based on existing variables
W_IP = W/IP,
L_IP = L/IP,
ShO_IP = ShO/IP,
SV_IP = SV/IP,
BS_IP = BS/IP,
TBF_IP = TBF/IP,
H_IP = H/IP,
R_IP = R/IP,
ER_IP = ER/IP,
HR_IP=HR/IP,
BB_IP=BB/IP,
IBB_IP=IBB/IP,
HBP_IP=HBP/IP,
WP_IP= WP/IP,
BK_IP=BK/IP,
SO_IP=SO/IP,
GB_IP = GB/IP, #Groundballs
FB_IP = FB/IP, #FlyBalls
LD_IP = LD/IP, #LineDrives
IFFB_IP = IFFB/IP, #Infield Fly balls
Balls_IP= Balls/IP,
Strikes_IP= Strikes/IP,
Pitches_IP= Pitches/IP,
RS_IP= RS/IP,
IFH_IP= IFH/IP,
BU_IP= BU/IP,
BUH_IP= BUH/IP,
Pulls_IP= Pulls/IP,
HLD_IP= HLD/IP,
SD_IP= SD/IP,
MD_IP= MD/IP,
Barrels_IP= Barrels/IP,
HardHits_IP= HardHit/IP
) %>% select(-L,-G,-IP,-ShO,-BS,-(TBF:BK),-(GB:BUH),-Pulls,-(SD:MD),-Barrels,-HardHit,-Events)
#will be removed after data is lagged -FIP,-(RAR:WPA),,-(wFB:wCH),-(`ERA-`:`xFIP-`),-SIERA,-(`RA9-WAR`:`Age Rng`),-kwERA,-`wCH (pi)`:`wSL (pi)`,`K/9+`:`HR/FB%+`)
#skim(pitcher_data4) %>% as_tibble()Repeat the process for Team Variables
FDG_Team5 = FDG_Team4 %>%
mutate( #create new variables based on existing variables
T_H_T_PA = T_H/T_PA,
T_x1B_T_PA = T_1B/T_PA, #note: R can't have variables start with a number
T_x2b_T_PA = T_2B/T_PA,
T_x3b_T_PA = T_3B/T_PA,
T_HR_T_PA = T_HR/T_PA,
T_R_T_PA = T_R/T_PA,
T_RBI_T_PA = T_RBI/T_PA,
T_BB_T_PA = T_BB/T_PA,
T_IBB_T_PA = T_IBB/T_PA,
T_SO_T_PA=T_SO/T_PA,
T_HBP_T_PA=T_HBP/T_PA,
T_SF_T_PA=T_SF/T_PA,
T_SH_T_PA=T_SH/T_PA,
T_GDP_T_PA= T_GDP/T_PA,#ground into double play
T_SB_T_PA=T_SB/T_PA,
T_CS_T_PA=T_CS/T_PA,
T_GB_T_PA = T_GB/T_PA, #Groundballs
T_FB_T_PA = T_FB/T_PA, #FlyBalls
T_LD_T_PA = T_LD/T_PA, #LineDrives
T_IFFB_T_PA = T_IFFB/T_PA, #Infield Fly balls
T_Pitches_T_PA= T_Pitches/T_PA,
T_Balls_T_PA= T_Balls/T_PA,
T_Strikes_T_PA= T_Strikes/T_PA,
T_IFH_T_PA= T_IFH/T_PA,
T_BU_T_PA= T_BU/T_PA,
T_BUH_T_PA= T_BUH/T_PA,
T_PH_T_PA= T_PH/T_PA,
T_Barrels_T_PA= T_Barrels/T_PA,
T_HardHits_T_PA= T_HardHit/T_PA
) %>% select(-(T_H:T_CS),-(T_GB:T_BUH),-T_PH,-T_Barrels,-T_HardHit,-T_Events) #Drop the old variables
#skim(FDG_Team5) %>% as_tibble()There are several ways to lag a dataset BY
GROUP.
* Dplyr way is here..
* The data.table (the method used below) is here.
#Note we will only be lagging the player level data, as the previous year's team performance shouldn't impact current performance
#Order the dataset by lag columns
pitcher_data5 = arrange(pitcher_data4, playerid,Season) #playerid is the Fangraph id assigned to each player
# Convert dataframe to data.table format
DT_pitcher = data.table(pitcher_data5)
#designate columns to lag - which is all of them
cols1 = colnames(pitcher_data5)
anscols = paste("lag", cols1, sep="_")
DT_pitcher[, (anscols) := data.table::shift(.SD, 1, NA, "lag"),by ='playerid', .SDcols=cols1] #Create 1 period lags by year
pitcher_data6 = as.data.frame(DT_pitcher) %>% select(-lag_playerid, -lag_Team, -lag_Season, -lag_Age,-lag_Name)
ncol(pitcher_data5) #251 - no lags[1] 251
ncol(pitcher_data6) #497 - lagged data ~ (251 * 2)-5[1] 497
We can use either the merge function or the SQL
functionality provided by the sqldf package to join the
lagged player level data to the Team level data
df_pitching_init = sqldf(
"
select a.*, b.*
from pitcher_data6 a
left join FDG_Team5 b
on a.Team = b.T_Team and a.Season = b.T_Season
"
) %>% select(-T_Team,-T_Season,-T_Age,-T_G,-T_AB)# Unncessary Team Variables
nrow(df_pitching_init) - nrow(pitcher_data6) #check if any rows are duplicated[1] 0
We can use Percentile based ranking to get rankings for players from the 2021 season.
Each player goes from a 0% to 100% on each percentile stat that is
used for creating a scoring opportunity. Data is not normalized by IP as
certain stats such as Wins will be worth more when we do.
#Categories I include are:
#Wins, Saves, WHIP, ERA, SOs, Holds
df_pitching_init2 = df_pitching_init %>%
# arrange(player_id,year) %>%
group_by(Season) %>%
mutate(
Wins_share = order(order(rank(W_IP,ties.method = 'average'),decreasing = FALSE))/n(),
SO_share = order(order(rank(SO_IP,ties.method = 'average'),decreasing = FALSE))/n(),
SV_share = order(order(rank(SV_IP,ties.method = 'average'),decreasing = FALSE))/n(),
WHIP_share = order(order(rank(WHIP,ties.method = 'average'),decreasing = FALSE))/n(),
ERA_share = order(order(rank(ERA,ties.method = 'average'),decreasing = FALSE))/n(),
HLD_share = order(order(rank(HLD_IP,ties.method = 'average'),decreasing = FALSE))/n(),
Worth = Wins_share+SO_share+SV_share+WHIP_share+ERA_share+HLD_share
) %>%
ungroup() Chart of the Distribution of initial percentiles
As the chart below shows, the data is roughly normal.
skewness((df_pitching_init2$Worth))[1] 0.1
ggplot2::qplot(df_pitching_init2$Worth, main="Total Pitching Worth Dataset") + geom_histogram(colour="black", fill="steelblue")`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
min(df_pitching_init2$Worth)[1] 0.88
max(df_pitching_init2$Worth)[1] 5.4
ggpubr::ggqqplot(df_pitching_init2$Worth)
shapiro.test(df_pitching_init2$Worth)
Shapiro-Wilk normality test
data: df_pitching_init2$Worth
W = 1, p-value = 0.0003
Total Rankings for the players (Using 6x6 Scoring) can be found here. While it looks like many of the top players have low worth scores, it is because we haven’t applied a modifier for IP yet. Wins are harder to come by relative to any other stat and require more innings pitched.
df_pitching_init2_raw = df_pitching_init %>%
# arrange(player_id,year) %>%
group_by(Season) %>%
mutate(
Wins_share_raw = order(order(rank(W,ties.method = 'average'),decreasing = FALSE))/n(),
SO_share_raw = order(order(rank(SO,ties.method = 'average'),decreasing = FALSE))/n(),
SV_share_raw = order(order(rank(SV,ties.method = 'average'),decreasing = FALSE))/n(),
WHIP_share = order(order(rank(WHIP,ties.method = 'average'),decreasing = FALSE))/n(),
ERA_share = order(order(rank(ERA,ties.method = 'average'),decreasing = FALSE))/n(),
HLD_share_raw = 0,
Worth = Wins_share_raw+SO_share_raw+SV_share_raw+WHIP_share+ERA_share+HLD_share_raw
) %>%
ungroup() %>%
select(-W,-SO,-SV,-WHIP,-ERA,-HLD)
options(digits=2)
df_pitching_init2021_raw =
df_pitching_init2_raw %>%
group_by(Name) %>%
filter(Season == 2021) %>%
arrange(desc(Worth)) %>%
select(Name,Wins_share_raw,SO_share_raw,SV_share_raw,WHIP_share,ERA_share,Worth)
df_pitching_init2021_raw %>%
filter (Worth>3.5) %>%
kbl() %>%
kable_material(c("striped", "hover","condensed","responsive"),full_width = F,fixed_thead = T)| Name | Wins_share_raw | SO_share_raw | SV_share_raw | WHIP_share | ERA_share | Worth |
|---|---|---|---|---|---|---|
| Daniel Bard | 0.79 | 0.69 | 0.97 | 0.87 | 0.75 | 4.0 |
| Garrett Richards | 0.79 | 0.84 | 0.86 | 0.87 | 0.68 | 4.0 |
| Jesus Luzardo | 0.77 | 0.78 | 0.55 | 0.89 | 0.92 | 3.9 |
| Brady Singer | 0.72 | 0.89 | 0.66 | 0.82 | 0.69 | 3.8 |
| Brad Keller | 0.86 | 0.85 | 0.31 | 0.92 | 0.77 | 3.7 |
| Jose Alvarado | 0.82 | 0.60 | 0.90 | 0.87 | 0.51 | 3.7 |
| Mitch Keller | 0.69 | 0.76 | 0.40 | 0.96 | 0.87 | 3.7 |
| Justus Sheffield | 0.81 | 0.56 | 0.37 | 0.98 | 0.95 | 3.7 |
| Nick Pivetta | 0.89 | 0.95 | 0.72 | 0.51 | 0.60 | 3.7 |
| Rafael Montero | 0.65 | 0.34 | 0.91 | 0.81 | 0.91 | 3.6 |
| Josh Fleming | 0.93 | 0.58 | 0.78 | 0.59 | 0.73 | 3.6 |
| Alec Mills | 0.74 | 0.73 | 0.71 | 0.69 | 0.73 | 3.6 |
| Joe Jimenez | 0.75 | 0.49 | 0.73 | 0.80 | 0.85 | 3.6 |
| Paul Fry | 0.58 | 0.52 | 0.83 | 0.80 | 0.87 | 3.6 |
| Wil Crowe | 0.61 | 0.82 | 0.53 | 0.84 | 0.78 | 3.6 |
| Erick Fedde | 0.82 | 0.87 | 0.38 | 0.70 | 0.78 | 3.5 |
| Adam Ottavino | 0.77 | 0.62 | 0.93 | 0.70 | 0.51 | 3.5 |
| Bryan Garcia | 0.50 | 0.22 | 0.85 | 0.98 | 0.98 | 3.5 |
| Alex Reyes | 0.92 | 0.77 | 0.98 | 0.58 | 0.25 | 3.5 |
While it looks like many of the top players have low worth scores, it is because we haven’t applied a modifier for IP yet.
options(digits=2)
df_pitching_init2021 =
df_pitching_init2 %>%
group_by(Name) %>%
filter(Season == 2021) %>%
arrange(desc(Worth)) %>%
select(Name,Wins_share,SO_share,SV_share,WHIP_share,ERA_share,HLD_share,Worth)
df_pitching_init2021 %>%
filter (Worth>2.9) %>%
kbl() %>%
kable_material(c("striped", "hover","condensed","responsive"),full_width = F,fixed_thead = T)| Name | Wins_share | SO_share | SV_share | WHIP_share | ERA_share | HLD_share | Worth |
|---|---|---|---|---|---|---|---|
| Paul Fry | 0.83 | 0.87 | 0.82 | 0.80 | 0.87 | 0.87 | 5.1 |
| Jose Alvarado | 0.96 | 0.85 | 0.89 | 0.87 | 0.51 | 0.93 | 5.0 |
| Daniel Bard | 0.93 | 0.85 | 0.97 | 0.87 | 0.75 | 0.61 | 5.0 |
| Joe Jimenez | 0.98 | 0.86 | 0.76 | 0.80 | 0.85 | 0.72 | 5.0 |
| Tanner Rainey | 0.22 | 0.93 | 0.89 | 0.93 | 0.97 | 0.95 | 4.9 |
| Adam Ottavino | 0.95 | 0.76 | 0.94 | 0.70 | 0.51 | 0.98 | 4.8 |
| Rafael Dolis | 0.63 | 0.84 | 0.89 | 0.95 | 0.81 | 0.68 | 4.8 |
| Tanner Scott | 0.87 | 0.90 | 0.40 | 0.84 | 0.74 | 0.93 | 4.7 |
| Ben Bowden | 0.83 | 0.82 | 0.57 | 0.97 | 0.92 | 0.53 | 4.6 |
| Ryan Hendrix | 1.00 | 0.73 | 0.51 | 0.82 | 0.85 | 0.68 | 4.6 |
| James Karinchak | 0.97 | 0.96 | 0.94 | 0.35 | 0.47 | 0.88 | 4.6 |
| Sean Newcomb | 0.62 | 0.93 | 0.79 | 0.93 | 0.65 | 0.62 | 4.5 |
| Pete Fairbanks | 0.71 | 0.92 | 0.90 | 0.69 | 0.35 | 0.96 | 4.5 |
| Bryan Abreu | 0.83 | 0.52 | 0.78 | 0.73 | 0.82 | 0.83 | 4.5 |
| Jeurys Familia | 0.99 | 0.84 | 0.72 | 0.66 | 0.45 | 0.81 | 4.5 |
| Brad Brach | 0.24 | 0.69 | 0.81 | 0.87 | 0.89 | 0.96 | 4.5 |
| Rafael Montero | 0.91 | 0.26 | 0.91 | 0.81 | 0.91 | 0.65 | 4.5 |
| Rex Brothers | 0.55 | 0.96 | 0.73 | 0.68 | 0.75 | 0.77 | 4.4 |
| Lucas Sims | 0.92 | 0.99 | 0.92 | 0.20 | 0.56 | 0.83 | 4.4 |
| Bryan Garcia | 0.76 | 0.21 | 0.85 | 0.98 | 0.98 | 0.64 | 4.4 |
| Trevor May | 0.94 | 0.92 | 0.86 | 0.43 | 0.35 | 0.90 | 4.4 |
| Enyel De Los Santos | 0.55 | 0.94 | 0.44 | 0.95 | 0.90 | 0.60 | 4.4 |
| Ryan Helsley | 0.97 | 0.52 | 0.75 | 0.67 | 0.61 | 0.85 | 4.4 |
| Aaron Bummer | 0.86 | 0.92 | 0.81 | 0.44 | 0.33 | 0.98 | 4.3 |
| Sam Howard | 0.66 | 0.92 | 0.33 | 0.73 | 0.80 | 0.88 | 4.3 |
| Amir Garrett | 0.04 | 0.89 | 0.92 | 0.83 | 0.86 | 0.77 | 4.3 |
| Tyler Chatwood | 0.22 | 0.80 | 0.80 | 0.72 | 0.81 | 0.95 | 4.3 |
| Sean Poppen | 0.39 | 0.79 | 0.83 | 0.96 | 0.74 | 0.58 | 4.3 |
| Adam Morgan | 0.80 | 0.72 | 0.88 | 0.56 | 0.53 | 0.78 | 4.3 |
| Gregory Soto | 0.89 | 0.83 | 0.96 | 0.59 | 0.28 | 0.71 | 4.3 |
| Alex Reyes | 0.98 | 0.90 | 0.98 | 0.58 | 0.25 | 0.57 | 4.3 |
| David Hess | 0.91 | 0.32 | 0.32 | 1.00 | 1.00 | 0.69 | 4.2 |
| Devin Williams | 0.99 | 0.99 | 0.86 | 0.31 | 0.09 | 0.99 | 4.2 |
| Aroldis Chapman | 0.93 | 1.00 | 0.99 | 0.52 | 0.27 | 0.51 | 4.2 |
| Trevor Megill | 0.35 | 0.90 | 0.40 | 0.98 | 0.99 | 0.57 | 4.2 |
| Phil Maton | 0.87 | 0.88 | 0.42 | 0.72 | 0.65 | 0.63 | 4.2 |
| Kyle Finnegan | 0.75 | 0.56 | 0.93 | 0.74 | 0.34 | 0.84 | 4.2 |
| Jake Diekman | 0.45 | 0.95 | 0.90 | 0.56 | 0.43 | 0.87 | 4.2 |
| Seth Lugo | 0.84 | 0.82 | 0.75 | 0.49 | 0.32 | 0.92 | 4.1 |
| Jake Brentz | 0.78 | 0.80 | 0.80 | 0.47 | 0.38 | 0.88 | 4.1 |
| J.B. Wendelken | 0.87 | 0.33 | 0.83 | 0.78 | 0.54 | 0.75 | 4.1 |
| Jeffrey Springs | 0.95 | 0.96 | 0.83 | 0.20 | 0.30 | 0.87 | 4.1 |
| Paul Sewald | 0.99 | 0.99 | 0.93 | 0.10 | 0.19 | 0.90 | 4.1 |
| Hansel Robles | 0.36 | 0.70 | 0.95 | 0.62 | 0.58 | 0.89 | 4.1 |
| Paul Campbell | 0.76 | 0.49 | 0.63 | 0.86 | 0.91 | 0.43 | 4.1 |
| Jacob Barnes | 0.26 | 0.78 | 0.87 | 0.73 | 0.88 | 0.55 | 4.1 |
| Josh Sborz | 0.67 | 0.78 | 0.72 | 0.67 | 0.45 | 0.77 | 4.1 |
| Carlos Estevez | 0.44 | 0.48 | 0.94 | 0.76 | 0.56 | 0.89 | 4.1 |
| Mychal Givens | 0.79 | 0.62 | 0.92 | 0.61 | 0.27 | 0.85 | 4.1 |
| Hirokazu Sawamura | 0.89 | 0.77 | 0.68 | 0.71 | 0.19 | 0.82 | 4.0 |
| Victor Gonzalez | 0.84 | 0.39 | 0.78 | 0.70 | 0.35 | 1.00 | 4.0 |
| Jesus Luzardo | 0.63 | 0.57 | 0.55 | 0.89 | 0.92 | 0.48 | 4.0 |
| Mike Mayers | 0.66 | 0.82 | 0.77 | 0.49 | 0.43 | 0.87 | 4.0 |
| Sean Doolittle | 0.60 | 0.66 | 0.74 | 0.72 | 0.60 | 0.70 | 4.0 |
| Joely Rodriguez | 0.36 | 0.54 | 0.75 | 0.81 | 0.63 | 0.92 | 4.0 |
| Anthony Misiewicz | 0.87 | 0.47 | 0.43 | 0.64 | 0.63 | 0.97 | 4.0 |
| Brett de Geus | 0.59 | 0.21 | 0.65 | 0.95 | 0.98 | 0.60 | 4.0 |
| Chris Stratton | 0.86 | 0.67 | 0.90 | 0.50 | 0.37 | 0.67 | 4.0 |
| Matt Foster | 0.49 | 0.55 | 0.77 | 0.70 | 0.85 | 0.59 | 4.0 |
| Heath Hembree | 0.25 | 0.96 | 0.92 | 0.30 | 0.79 | 0.73 | 4.0 |
| Camilo Doval | 1.00 | 0.94 | 0.90 | 0.13 | 0.17 | 0.81 | 4.0 |
| Kyle Zimmer | 0.74 | 0.26 | 0.81 | 0.65 | 0.68 | 0.81 | 4.0 |
| Shane Greene | 0.01 | 0.57 | 0.83 | 0.91 | 0.96 | 0.66 | 3.9 |
| Darwinzon Hernandez | 0.47 | 0.93 | 0.53 | 0.77 | 0.28 | 0.94 | 3.9 |
| Archie Bradley | 0.98 | 0.17 | 0.82 | 0.68 | 0.39 | 0.90 | 3.9 |
| Brad Boxberger | 0.78 | 0.90 | 0.86 | 0.15 | 0.26 | 0.98 | 3.9 |
| Sean Reid-Foley | 0.90 | 0.89 | 0.36 | 0.77 | 0.75 | 0.24 | 3.9 |
| Matt Andriese | 0.33 | 0.59 | 0.74 | 0.88 | 0.75 | 0.62 | 3.9 |
| Reid Detmers | 0.44 | 0.39 | 0.67 | 0.97 | 0.97 | 0.46 | 3.9 |
| Kevin Ginkel | 0.09 | 0.70 | 0.54 | 0.82 | 0.89 | 0.85 | 3.9 |
| Stefan Crichton | 0.05 | 0.11 | 0.93 | 0.99 | 0.96 | 0.86 | 3.9 |
| Luis Oviedo | 0.24 | 0.62 | 0.63 | 0.99 | 0.99 | 0.42 | 3.9 |
| Jose Cisnero | 0.64 | 0.53 | 0.87 | 0.54 | 0.38 | 0.93 | 3.9 |
| Codi Heuer | 0.92 | 0.22 | 0.79 | 0.53 | 0.54 | 0.90 | 3.9 |
| Glenn Otto | 0.10 | 0.83 | 0.61 | 0.93 | 0.99 | 0.41 | 3.9 |
| Aaron Ashby | 0.90 | 0.86 | 0.80 | 0.28 | 0.61 | 0.44 | 3.9 |
| Daniel Norris | 0.26 | 0.54 | 0.72 | 0.76 | 0.87 | 0.73 | 3.9 |
| Greg Holland | 0.52 | 0.43 | 0.91 | 0.57 | 0.68 | 0.76 | 3.9 |
| Nick Mears | 0.36 | 0.50 | 0.66 | 0.90 | 0.71 | 0.74 | 3.9 |
| Brooks Raley | 0.32 | 0.92 | 0.82 | 0.32 | 0.67 | 0.81 | 3.8 |
| Joakim Soria | 0.17 | 0.66 | 0.92 | 0.61 | 0.72 | 0.74 | 3.8 |
| Sam Coonrod | 0.42 | 0.75 | 0.84 | 0.53 | 0.47 | 0.82 | 3.8 |
| Jacob Webb | 0.98 | 0.45 | 0.79 | 0.79 | 0.50 | 0.31 | 3.8 |
| Richard Lovelady | 0.91 | 0.74 | 0.85 | 0.15 | 0.32 | 0.84 | 3.8 |
| Austin Voth | 0.70 | 0.57 | 0.29 | 0.74 | 0.76 | 0.73 | 3.8 |
| Corey Knebel | 0.99 | 0.81 | 0.90 | 0.06 | 0.08 | 0.91 | 3.8 |
| Trevor Stephan | 0.42 | 0.81 | 0.71 | 0.66 | 0.57 | 0.59 | 3.8 |
| Griffin Canning | 0.80 | 0.51 | 0.54 | 0.75 | 0.80 | 0.35 | 3.8 |
| Hector Neris | 0.51 | 0.91 | 0.93 | 0.26 | 0.37 | 0.77 | 3.8 |
| Demarcus Evans | 0.10 | 0.87 | 0.60 | 0.81 | 0.74 | 0.64 | 3.8 |
| Bryan Shaw | 0.77 | 0.36 | 0.77 | 0.62 | 0.32 | 0.90 | 3.7 |
| Anthony Castro | 0.32 | 0.91 | 0.82 | 0.44 | 0.66 | 0.57 | 3.7 |
| Brad Hand | 0.88 | 0.41 | 0.97 | 0.45 | 0.44 | 0.58 | 3.7 |
| Taylor Rogers | 0.46 | 0.97 | 0.95 | 0.23 | 0.27 | 0.84 | 3.7 |
| Tim Hill | 0.91 | 0.41 | 0.72 | 0.40 | 0.37 | 0.93 | 3.7 |
| Chad Green | 0.96 | 0.81 | 0.87 | 0.02 | 0.20 | 0.86 | 3.7 |
| Kyle Keller | 0.21 | 0.67 | 0.47 | 0.83 | 0.92 | 0.61 | 3.7 |
| Mason Thompson | 0.33 | 0.41 | 0.63 | 0.98 | 0.46 | 0.89 | 3.7 |
| Alex Lange | 0.19 | 0.71 | 0.78 | 0.77 | 0.47 | 0.79 | 3.7 |
| Diego Castillo | 0.84 | 0.89 | 0.96 | 0.08 | 0.13 | 0.80 | 3.7 |
| Anthony Kay | 0.20 | 0.79 | 0.59 | 0.92 | 0.81 | 0.39 | 3.7 |
| Josh Taylor | 0.15 | 0.87 | 0.75 | 0.68 | 0.29 | 0.95 | 3.7 |
| Conner Greene | 0.30 | 0.58 | 0.35 | 0.95 | 0.95 | 0.56 | 3.7 |
| Scott Barlow | 0.67 | 0.85 | 0.95 | 0.32 | 0.07 | 0.82 | 3.7 |
| Aaron Slegers | 0.64 | 0.20 | 0.30 | 0.98 | 0.95 | 0.62 | 3.7 |
| Kyle Funkhouser | 0.92 | 0.37 | 0.71 | 0.65 | 0.30 | 0.74 | 3.7 |
| Tommy Nance | 0.26 | 0.63 | 0.47 | 0.55 | 0.96 | 0.80 | 3.7 |
| Spencer Howard | 0.11 | 0.62 | 0.65 | 0.88 | 0.97 | 0.44 | 3.7 |
| Edwin Uceta | 0.10 | 0.86 | 0.59 | 0.80 | 0.93 | 0.39 | 3.7 |
| Michael Lorenzen | 0.25 | 0.10 | 0.91 | 0.63 | 0.80 | 0.98 | 3.7 |
| Brusdar Graterol | 0.87 | 0.20 | 0.58 | 0.66 | 0.62 | 0.73 | 3.7 |
| Jordan Romano | 0.94 | 0.93 | 0.97 | 0.13 | 0.04 | 0.64 | 3.7 |
| Michael Fulmer | 0.72 | 0.61 | 0.94 | 0.47 | 0.17 | 0.74 | 3.7 |
| Alex Colome | 0.61 | 0.31 | 0.96 | 0.64 | 0.49 | 0.64 | 3.7 |
| Yimi Garcia | 0.69 | 0.60 | 0.96 | 0.25 | 0.51 | 0.63 | 3.7 |
| Spencer Patton | 0.42 | 0.75 | 0.84 | 0.32 | 0.42 | 0.90 | 3.6 |
| Alex Claudio | 0.22 | 0.38 | 0.79 | 0.86 | 0.79 | 0.61 | 3.6 |
| Matt Barnes | 0.94 | 0.98 | 0.98 | 0.21 | 0.41 | 0.11 | 3.6 |
| Matt Wisler | 0.62 | 0.89 | 0.74 | 0.15 | 0.39 | 0.85 | 3.6 |
| Rowan Wick | 0.04 | 0.86 | 0.95 | 0.58 | 0.54 | 0.66 | 3.6 |
| Wander Suero | 0.42 | 0.60 | 0.31 | 0.66 | 0.89 | 0.75 | 3.6 |
| Justin Garza | 0.71 | 0.56 | 0.53 | 0.84 | 0.65 | 0.34 | 3.6 |
| Cionel Perez | 0.34 | 0.59 | 0.51 | 0.93 | 0.90 | 0.34 | 3.6 |
| Blake Treinen | 0.82 | 0.80 | 0.89 | 0.07 | 0.04 | 0.99 | 3.6 |
| Giovanny Gallegos | 0.74 | 0.80 | 0.93 | 0.02 | 0.18 | 0.94 | 3.6 |
| Wandy Peralta | 0.90 | 0.24 | 0.89 | 0.62 | 0.27 | 0.69 | 3.6 |
| Max Kranick | 0.50 | 0.23 | 0.63 | 0.94 | 0.89 | 0.43 | 3.6 |
| Michael Rucker | 0.08 | 0.63 | 0.81 | 0.80 | 0.95 | 0.33 | 3.6 |
| J.D. Hammer | 0.47 | 0.70 | 0.51 | 0.88 | 0.70 | 0.34 | 3.6 |
| Tim Mayza | 0.89 | 0.65 | 0.73 | 0.08 | 0.29 | 0.97 | 3.6 |
| Zac Lowther | 0.24 | 0.56 | 0.57 | 0.91 | 0.93 | 0.38 | 3.6 |
| Ryne Stanek | 0.37 | 0.84 | 0.79 | 0.34 | 0.30 | 0.95 | 3.6 |
| Dylan Floro | 0.88 | 0.45 | 0.96 | 0.36 | 0.14 | 0.79 | 3.6 |
| Jackson Kowar | 0.10 | 0.44 | 0.62 | 1.00 | 1.00 | 0.42 | 3.6 |
| Cesar Valdez | 0.36 | 0.47 | 0.93 | 0.91 | 0.84 | 0.06 | 3.6 |
| Justus Sheffield | 0.85 | 0.17 | 0.37 | 0.98 | 0.95 | 0.25 | 3.6 |
| Lucas Gilbreath | 0.72 | 0.60 | 0.76 | 0.52 | 0.28 | 0.68 | 3.6 |
| Albert Abreu | 0.52 | 0.44 | 0.78 | 0.42 | 0.74 | 0.65 | 3.5 |
| Lou Trivino | 0.89 | 0.34 | 0.97 | 0.41 | 0.22 | 0.71 | 3.5 |
| Michael Feliz | 0.02 | 0.70 | 0.85 | 0.91 | 0.96 | 0.10 | 3.5 |
| Phillips Valdez | 0.47 | 0.29 | 0.76 | 0.58 | 0.84 | 0.59 | 3.5 |
| Garrett Richards | 0.49 | 0.24 | 0.75 | 0.87 | 0.68 | 0.50 | 3.5 |
| Chris Rodriguez | 0.68 | 0.50 | 0.64 | 0.71 | 0.38 | 0.63 | 3.5 |
| Junior Guerra | 0.76 | 0.38 | 0.05 | 0.94 | 0.86 | 0.54 | 3.5 |
| Trevor Richards | 0.93 | 0.84 | 0.71 | 0.05 | 0.32 | 0.68 | 3.5 |
| Keynan Middleton | 0.23 | 0.16 | 0.91 | 0.85 | 0.69 | 0.69 | 3.5 |
| Daniel Lynch | 0.58 | 0.20 | 0.62 | 0.90 | 0.81 | 0.41 | 3.5 |
| Edward Cabrera | 0.10 | 0.64 | 0.62 | 0.90 | 0.83 | 0.42 | 3.5 |
| Tyler Zuber | 0.09 | 0.36 | 0.58 | 0.84 | 0.88 | 0.76 | 3.5 |
| Adam Plutko | 0.13 | 0.17 | 0.73 | 0.90 | 0.94 | 0.67 | 3.5 |
| Brent Suter | 1.00 | 0.40 | 0.70 | 0.52 | 0.20 | 0.71 | 3.5 |
| Jose Quijada | 0.07 | 0.98 | 0.48 | 0.60 | 0.61 | 0.78 | 3.5 |
| Shawn Armstrong | 0.18 | 0.84 | 0.17 | 0.77 | 0.94 | 0.60 | 3.5 |
| Garrett Crochet | 0.53 | 0.83 | 0.67 | 0.46 | 0.15 | 0.86 | 3.5 |
| Garrett Whitlock | 0.94 | 0.72 | 0.77 | 0.20 | 0.03 | 0.83 | 3.5 |
| Cole Sulser | 0.80 | 0.77 | 0.91 | 0.21 | 0.12 | 0.68 | 3.5 |
| Jose Quintana | 0.02 | 0.93 | 0.13 | 0.94 | 0.91 | 0.54 | 3.5 |
| Josh Fleming | 0.89 | 0.04 | 0.69 | 0.59 | 0.73 | 0.54 | 3.5 |
| A.J. Minter | 0.56 | 0.68 | 0.46 | 0.37 | 0.41 | 0.99 | 3.5 |
| Brady Singer | 0.29 | 0.54 | 0.66 | 0.82 | 0.69 | 0.46 | 3.5 |
| Alex Young | 0.29 | 0.22 | 0.44 | 0.96 | 0.92 | 0.64 | 3.5 |
| Genesis Cabrera | 0.56 | 0.70 | 0.39 | 0.44 | 0.40 | 0.99 | 3.5 |
| Brandon Bielak | 0.59 | 0.36 | 0.74 | 0.63 | 0.59 | 0.56 | 3.5 |
| Alex Vesia | 0.75 | 0.94 | 0.77 | 0.08 | 0.06 | 0.86 | 3.4 |
| Patrick Murphy | 0.08 | 0.58 | 0.52 | 0.72 | 0.74 | 0.81 | 3.4 |
| Andrew Wantz | 0.28 | 0.95 | 0.66 | 0.40 | 0.70 | 0.45 | 3.4 |
| Emilio Pagan | 0.63 | 0.68 | 0.27 | 0.26 | 0.68 | 0.91 | 3.4 |
| Craig Kimbrel | 0.67 | 1.00 | 0.98 | 0.02 | 0.06 | 0.70 | 3.4 |
| Bailey Falter | 0.59 | 0.55 | 0.56 | 0.32 | 0.81 | 0.61 | 3.4 |
| Wade Davis | 0.01 | 0.32 | 0.84 | 0.74 | 0.94 | 0.58 | 3.4 |
| Austin Davis | 0.29 | 0.64 | 0.37 | 0.62 | 0.73 | 0.78 | 3.4 |
| Derek Holland | 0.60 | 0.59 | 0.03 | 0.83 | 0.72 | 0.65 | 3.4 |
| Will Vest | 0.19 | 0.16 | 0.53 | 0.88 | 0.87 | 0.79 | 3.4 |
| Kendall Graveman | 0.86 | 0.68 | 0.94 | 0.08 | 0.02 | 0.84 | 3.4 |
| Jay Jackson | 0.88 | 0.91 | 0.07 | 0.40 | 0.40 | 0.75 | 3.4 |
| Dinelson Lamet | 0.34 | 0.83 | 0.37 | 0.76 | 0.57 | 0.52 | 3.4 |
| J.P. Feyereisen | 0.72 | 0.41 | 0.86 | 0.38 | 0.12 | 0.91 | 3.4 |
| Yency Almonte | 0.14 | 0.50 | 0.29 | 0.86 | 0.97 | 0.62 | 3.4 |
| Brandon Kintzler | 0.68 | 0.13 | 0.10 | 0.96 | 0.90 | 0.63 | 3.4 |
| Josh Staumont | 0.61 | 0.71 | 0.88 | 0.16 | 0.16 | 0.89 | 3.4 |
| Austin Adams | 0.56 | 0.97 | 0.24 | 0.32 | 0.48 | 0.83 | 3.4 |
| Phil Bickford | 0.79 | 0.77 | 0.73 | 0.16 | 0.14 | 0.80 | 3.4 |
| Keegan Thompson | 0.54 | 0.58 | 0.73 | 0.74 | 0.28 | 0.51 | 3.4 |
| Bruce Zimmermann | 0.62 | 0.29 | 0.58 | 0.79 | 0.72 | 0.39 | 3.4 |
| Miguel Diaz | 0.72 | 0.68 | 0.76 | 0.31 | 0.37 | 0.52 | 3.4 |
| Anthony Banda | 0.59 | 0.44 | 0.26 | 0.81 | 0.53 | 0.72 | 3.4 |
| Humberto Mejia | 0.10 | 0.33 | 0.60 | 0.98 | 0.96 | 0.40 | 3.4 |
| Edwin Diaz | 0.80 | 0.96 | 0.99 | 0.13 | 0.31 | 0.18 | 3.4 |
| Buck Farmer | 0.04 | 0.61 | 0.27 | 0.94 | 0.90 | 0.60 | 3.4 |
| Jonathan Loaisiga | 0.97 | 0.49 | 0.87 | 0.10 | 0.05 | 0.88 | 3.4 |
| Shane McClanahan | 0.81 | 0.76 | 0.62 | 0.46 | 0.31 | 0.41 | 3.4 |
| Josiah Gray | 0.19 | 0.67 | 0.66 | 0.60 | 0.78 | 0.45 | 3.4 |
| Jeff Hoffman | 0.32 | 0.66 | 0.38 | 0.85 | 0.61 | 0.53 | 3.4 |
| Caleb Baragar | 0.84 | 0.08 | 0.88 | 0.59 | 0.02 | 0.94 | 3.4 |
| Miguel Sanchez | 0.77 | 0.31 | 0.56 | 0.85 | 0.49 | 0.37 | 3.4 |
| Hoby Milner | 0.03 | 0.96 | 0.20 | 0.79 | 0.77 | 0.58 | 3.3 |
| Braxton Garrett | 0.20 | 0.40 | 0.63 | 0.97 | 0.71 | 0.42 | 3.3 |
| Luke Farrell | 0.32 | 0.57 | 0.29 | 0.92 | 0.66 | 0.57 | 3.3 |
| Dylan Cease | 0.79 | 0.94 | 0.45 | 0.42 | 0.44 | 0.28 | 3.3 |
| A.J. Alexy | 0.97 | 0.11 | 0.64 | 0.51 | 0.65 | 0.43 | 3.3 |
| Nick Wittgren | 0.23 | 0.48 | 0.71 | 0.41 | 0.72 | 0.76 | 3.3 |
| Sergio Romo | 0.12 | 0.48 | 0.84 | 0.40 | 0.64 | 0.83 | 3.3 |
| Andrew Kittredge | 0.96 | 0.66 | 0.90 | 0.07 | 0.03 | 0.69 | 3.3 |
| JC Mejia | 0.13 | 0.33 | 0.59 | 0.88 | 0.99 | 0.40 | 3.3 |
| Cody Poteet | 0.66 | 0.62 | 0.47 | 0.57 | 0.71 | 0.29 | 3.3 |
| Daniel Hudson | 0.90 | 0.97 | 0.07 | 0.17 | 0.26 | 0.95 | 3.3 |
| Tyler Duffey | 0.43 | 0.48 | 0.84 | 0.36 | 0.22 | 0.97 | 3.3 |
| Mitch Keller | 0.46 | 0.35 | 0.40 | 0.96 | 0.87 | 0.26 | 3.3 |
| Ryan Borucki | 0.97 | 0.34 | 0.34 | 0.38 | 0.70 | 0.57 | 3.3 |
| Clay Holmes | 0.95 | 0.72 | 0.22 | 0.26 | 0.36 | 0.78 | 3.3 |
| Tejay Antone | 0.59 | 0.87 | 0.88 | 0.02 | 0.04 | 0.88 | 3.3 |
| Nick Pivetta | 0.57 | 0.74 | 0.68 | 0.51 | 0.60 | 0.20 | 3.3 |
| Blake Taylor | 0.89 | 0.46 | 0.34 | 0.66 | 0.22 | 0.72 | 3.3 |
| Michael Kopech | 0.57 | 0.98 | 0.37 | 0.22 | 0.32 | 0.82 | 3.3 |
| Tarik Skubal | 0.51 | 0.69 | 0.64 | 0.45 | 0.55 | 0.43 | 3.3 |
| Justin Steele | 0.70 | 0.58 | 0.38 | 0.58 | 0.53 | 0.50 | 3.3 |
| Joe Smith | 0.92 | 0.28 | 0.02 | 0.64 | 0.71 | 0.70 | 3.3 |
| Sam Hentges | 0.12 | 0.51 | 0.45 | 0.96 | 0.93 | 0.28 | 3.3 |
| Brandon Workman | 0.27 | 0.32 | 0.14 | 0.99 | 0.78 | 0.76 | 3.2 |
| Raisel Iglesias | 0.91 | 0.98 | 0.99 | 0.04 | 0.10 | 0.25 | 3.2 |
| Andrew Heaney | 0.62 | 0.77 | 0.30 | 0.53 | 0.84 | 0.19 | 3.2 |
| Sammy Long | 0.45 | 0.40 | 0.66 | 0.48 | 0.79 | 0.46 | 3.2 |
| Ryan Pressly | 0.78 | 0.87 | 0.98 | 0.06 | 0.06 | 0.50 | 3.2 |
| Josh Tomlin | 0.81 | 0.13 | 0.09 | 0.77 | 0.92 | 0.52 | 3.2 |
| Kohei Arihara | 0.45 | 0.03 | 0.67 | 0.69 | 0.93 | 0.46 | 3.2 |
| Eduardo Rodriguez | 0.82 | 0.79 | 0.19 | 0.64 | 0.66 | 0.13 | 3.2 |
| Chad Kuhl | 0.62 | 0.38 | 0.28 | 0.68 | 0.68 | 0.59 | 3.2 |
| Robert Stephenson | 0.36 | 0.74 | 0.75 | 0.50 | 0.20 | 0.66 | 3.2 |
| Travis Lakins Sr. | 0.27 | 0.27 | 0.46 | 0.69 | 0.83 | 0.71 | 3.2 |
| Dan Winkler | 0.17 | 0.54 | 0.16 | 0.82 | 0.75 | 0.77 | 3.2 |
| David Peterson | 0.21 | 0.60 | 0.57 | 0.65 | 0.79 | 0.38 | 3.2 |
| Carson Fulmer | 0.06 | 0.42 | 0.43 | 0.80 | 0.93 | 0.56 | 3.2 |
| Tylor Megill | 0.39 | 0.72 | 0.61 | 0.48 | 0.60 | 0.41 | 3.2 |
| Connor Brogdon | 0.85 | 0.29 | 0.72 | 0.23 | 0.30 | 0.80 | 3.2 |
| Caleb Thielbar | 0.93 | 0.83 | 0.10 | 0.26 | 0.25 | 0.82 | 3.2 |
| Taylor Clarke | 0.16 | 0.33 | 0.40 | 0.80 | 0.71 | 0.79 | 3.2 |
| Tony Gonsolin | 0.73 | 0.79 | 0.50 | 0.59 | 0.25 | 0.32 | 3.2 |
| Yusmeiro Petit | 0.92 | 0.01 | 0.77 | 0.12 | 0.44 | 0.92 | 3.2 |
| Anthony Bender | 0.44 | 0.78 | 0.84 | 0.15 | 0.13 | 0.84 | 3.2 |
| David Price | 0.68 | 0.18 | 0.69 | 0.67 | 0.46 | 0.49 | 3.2 |
| Austin Warren | 0.99 | 0.50 | 0.85 | 0.11 | 0.02 | 0.69 | 3.2 |
| Wil Crowe | 0.25 | 0.42 | 0.53 | 0.84 | 0.78 | 0.35 | 3.2 |
| Alexander Wells | 0.42 | 0.03 | 0.53 | 0.89 | 0.94 | 0.35 | 3.2 |
| Luis Patino | 0.64 | 0.43 | 0.65 | 0.46 | 0.54 | 0.44 | 3.2 |
| David Bednar | 0.46 | 0.88 | 0.85 | 0.07 | 0.05 | 0.86 | 3.2 |
| Chris Martin | 0.41 | 0.15 | 0.76 | 0.45 | 0.45 | 0.94 | 3.2 |
| John King | 0.99 | 0.28 | 0.63 | 0.25 | 0.33 | 0.66 | 3.1 |
| Sam Clay | 0.05 | 0.14 | 0.34 | 0.93 | 0.80 | 0.89 | 3.1 |
| Daniel Ponce de Leon | 0.21 | 0.10 | 0.86 | 0.89 | 0.87 | 0.21 | 3.1 |
| Cristian Javier | 0.30 | 0.88 | 0.74 | 0.29 | 0.34 | 0.59 | 3.1 |
| Randy Dobnak | 0.14 | 0.01 | 0.74 | 0.82 | 0.98 | 0.45 | 3.1 |
| Sean Guenther | 0.09 | 0.12 | 0.56 | 0.99 | 1.00 | 0.37 | 3.1 |
| Brad Keller | 0.59 | 0.32 | 0.31 | 0.92 | 0.77 | 0.20 | 3.1 |
| Jordan Holloway | 0.54 | 0.53 | 0.60 | 0.60 | 0.46 | 0.40 | 3.1 |
| Shaun Anderson | 0.07 | 0.21 | 0.51 | 1.00 | 0.99 | 0.33 | 3.1 |
| Logan Gilbert | 0.47 | 0.65 | 0.64 | 0.27 | 0.65 | 0.43 | 3.1 |
| Wes Benjamin | 0.07 | 0.26 | 0.48 | 0.99 | 0.99 | 0.30 | 3.1 |
| Jake Cousins | 0.24 | 0.97 | 0.62 | 0.27 | 0.12 | 0.87 | 3.1 |
| Collin McHugh | 0.88 | 0.77 | 0.71 | 0.04 | 0.02 | 0.68 | 3.1 |
| Chris Paddack | 0.64 | 0.35 | 0.56 | 0.45 | 0.73 | 0.37 | 3.1 |
| Jorge Alcala | 0.48 | 0.56 | 0.72 | 0.07 | 0.45 | 0.81 | 3.1 |
| Packy Naughton | 0.11 | 0.01 | 0.65 | 0.97 | 0.90 | 0.44 | 3.1 |
| Junior Fernandez | 0.44 | 0.12 | 0.44 | 0.99 | 0.81 | 0.28 | 3.1 |
| Luis Garcia | 0.71 | 0.65 | 0.66 | 0.30 | 0.32 | 0.45 | 3.1 |
| Yusei Kikuchi | 0.38 | 0.59 | 0.60 | 0.54 | 0.57 | 0.40 | 3.1 |
| Dominic Leone | 0.75 | 0.39 | 0.81 | 0.19 | 0.01 | 0.92 | 3.1 |
| Matt Peacock | 0.57 | 0.02 | 0.58 | 0.83 | 0.69 | 0.38 | 3.1 |
| Dean Kremer | 0.07 | 0.31 | 0.50 | 0.90 | 0.98 | 0.32 | 3.1 |
| Vladimir Gutierrez | 0.79 | 0.16 | 0.49 | 0.66 | 0.66 | 0.31 | 3.1 |
| Pierce Johnson | 0.49 | 0.91 | 0.21 | 0.44 | 0.24 | 0.78 | 3.1 |
| Shane Bieber | 0.73 | 0.95 | 0.51 | 0.34 | 0.22 | 0.33 | 3.1 |
| Alek Manoah | 0.81 | 0.75 | 0.67 | 0.13 | 0.24 | 0.46 | 3.1 |
| Joe Kelly | 0.39 | 0.74 | 0.83 | 0.07 | 0.15 | 0.87 | 3.1 |
| Griffin Jax | 0.43 | 0.18 | 0.57 | 0.59 | 0.90 | 0.38 | 3.1 |
| Matt Manning | 0.41 | 0.06 | 0.58 | 0.79 | 0.83 | 0.38 | 3.1 |
| Hyeon-jong Yang | 0.11 | 0.09 | 0.67 | 0.91 | 0.80 | 0.47 | 3.1 |
| Zack Littell | 0.65 | 0.56 | 0.80 | 0.23 | 0.16 | 0.65 | 3.0 |
| Erick Fedde | 0.50 | 0.44 | 0.38 | 0.70 | 0.78 | 0.25 | 3.0 |
| Kenta Maeda | 0.54 | 0.63 | 0.45 | 0.51 | 0.64 | 0.28 | 3.0 |
| Cody Ponce | 0.06 | 0.40 | 0.41 | 0.95 | 0.95 | 0.26 | 3.0 |
| Jharel Cotton | 0.66 | 0.50 | 0.22 | 0.65 | 0.33 | 0.69 | 3.0 |
| Liam Hendriks | 0.95 | 0.99 | 0.99 | 0.01 | 0.09 | 0.02 | 3.0 |
| Jorge Lopez | 0.16 | 0.36 | 0.25 | 0.89 | 0.86 | 0.50 | 3.0 |
| Caleb Smith | 0.26 | 0.69 | 0.28 | 0.62 | 0.68 | 0.51 | 3.0 |
| Taylor Widener | 0.19 | 0.59 | 0.48 | 0.71 | 0.56 | 0.49 | 3.0 |
| Ryan Thompson | 0.86 | 0.68 | 0.35 | 0.11 | 0.07 | 0.96 | 3.0 |
| Art Warren | 0.98 | 0.99 | 0.43 | 0.02 | 0.01 | 0.59 | 3.0 |
| Ryan Weathers | 0.34 | 0.15 | 0.69 | 0.63 | 0.76 | 0.45 | 3.0 |
| Tyler Rogers | 0.84 | 0.07 | 0.92 | 0.16 | 0.05 | 0.98 | 3.0 |
| Andrew Miller | 0.01 | 0.72 | 0.06 | 0.85 | 0.67 | 0.72 | 3.0 |
| Keegan Akin | 0.14 | 0.28 | 0.50 | 0.85 | 0.93 | 0.32 | 3.0 |
| Jarlin Garcia | 0.85 | 0.51 | 0.70 | 0.05 | 0.11 | 0.79 | 3.0 |
| Joe Ryan | 0.76 | 0.75 | 0.61 | 0.01 | 0.47 | 0.41 | 3.0 |
| Eli Morgan | 0.54 | 0.34 | 0.57 | 0.43 | 0.76 | 0.37 | 3.0 |
| Tyler Kinley | 0.35 | 0.46 | 0.43 | 0.34 | 0.66 | 0.76 | 3.0 |
| Yohan Ramirez | 0.27 | 0.89 | 0.88 | 0.18 | 0.44 | 0.33 | 3.0 |
| Taylor Hearn | 0.56 | 0.31 | 0.43 | 0.53 | 0.63 | 0.48 | 3.0 |
| Yacksel Rios | 0.94 | 0.25 | 0.28 | 0.39 | 0.53 | 0.55 | 2.9 |
| Tyler Clippard | 0.30 | 0.23 | 0.96 | 0.50 | 0.23 | 0.72 | 2.9 |
| Carlos Hernandez | 0.71 | 0.28 | 0.65 | 0.48 | 0.38 | 0.44 | 2.9 |
| Kris Bubic | 0.40 | 0.30 | 0.61 | 0.63 | 0.58 | 0.41 | 2.9 |
| Johan Oviedo | 0.11 | 0.21 | 0.65 | 0.84 | 0.69 | 0.44 | 2.9 |
| Dane Dunning | 0.35 | 0.46 | 0.50 | 0.70 | 0.59 | 0.32 | 2.9 |
| Nick Sandlin | 0.20 | 0.97 | 0.59 | 0.23 | 0.17 | 0.77 | 2.9 |
| Kyle Muller | 0.53 | 0.54 | 0.56 | 0.42 | 0.50 | 0.37 | 2.9 |
| Luis Garcia | 0.21 | 0.56 | 0.86 | 0.08 | 0.25 | 0.96 | 2.9 |
| Luis Gil | 0.25 | 0.90 | 0.60 | 0.55 | 0.20 | 0.40 | 2.9 |
| Robert Dugger | 0.07 | 0.13 | 0.47 | 0.97 | 0.96 | 0.30 | 2.9 |
Not all variables can be used for predictive modeling. Variables that
go into the percentile ranking or are non-normalized metrics created
after the fact (such as WAR - Wins above Replacement or
RS - Raw Run Support) should be removed. However, metrics
that are normalized by a per pitch basis (such as wFB/C)
can remain as we expect pitchers to have similar performance in these
metrics one year out.
#Be careful about RS - Run Support and RS/9
#Creating a new dataset to keep original intact
df_pitching_init3 = df_pitching_init2 %>%
select (-Name)Lagged Percentile (_share) Variables can be used for
predictive modeling. However since these variables were created for the
Worth metric they must also be removed for modeling purposes.
#Order the dataset by lag columns
df_pitching_init4 = arrange(df_pitching_init3, playerid,Season) #playerid is the Fangraph id assigned to each player
# Convert dataframe to data.table format
DT_pitcher2 = data.table(df_pitching_init4)
#designate columns to lag - just the new shares
cols1 = (c('Wins_share','SO_share','SV_share', 'ERA_share','WHIP_share','HLD_share','Worth'))
anscols = paste("lag", cols1, sep="_")
DT_pitcher2[, (anscols) := data.table::shift(.SD, 1, NA, "lag"),by ='playerid', .SDcols=cols1] #Create 1 period lags by year
df_pitching_final = as.data.frame(DT_pitcher2) %>%
select(-c(Wins_share,SO_share,SV_share, ERA_share,WHIP_share,HLD_share))%>%
select(-FIP,-(RAR:WPA),-(wFB:wCH),-(`ERA-`:`xFIP-`),
-SIERA,-(`RA9-WAR`:`Age Rng`),-kwERA,-(`wCH (pi)`:`wSL (pi)`),-(`K/9+`:`HR/FB%+`)) %>% select(-W,-SO,-SV,-HLD,-W_IP,-SO_IP,-SV_IP,-WHIP,-ERA,-HLD_IP)We split the data into Training Data (which is used to create the model) and test data (which is used to validate the model)
set.seed(15674) # For reproducibility
# Create index for testing and training data
inTrain <- createDataPartition(y = df_pitching_final$Worth, p = 0.80, list = FALSE)
# subset pitching data for training
tr_2021 <- df_pitching_final[inTrain,]
# subset the rest to test and validate trained model
te_2021 <- df_pitching_final[-inTrain,]
nrow(tr_2021)/nrow(df_pitching_final) #check if split is 0.8[1] 0.8
Vtreat Package in R is excellent for treating data before using for modeling. Additional documentation can be found here.
treat_plan_2021 <- vtreat::designTreatmentsZ(
dframe = tr_2021, # training data
varlist = colnames(tr_2021) %>% .[. != "hitting_score1"], # input variables = all training data columns, except random
codeRestriction = c("clean", "isBAD", "lev"), # derived variables types (drop cat_P)
verbose = FALSE) # suppress messages
#clean stands for cleaned numerical variable, isBAD indicates that a value replacement has occurred (which indicates a missing value in this case), and lev is a binary indicator whether a particular value of that categorical variable was present.
#### Checking Scoreframe
score_frame <- treat_plan_2021$scoreFrame %>%
select(varName, origName, code)
head(score_frame)
tr_treated_2021 <- vtreat::prepare(treat_plan_2021, tr_2021)
te_treated_2021 <- vtreat::prepare(treat_plan_2021, te_2021)
treat_plan_2021 <- vtreat::designTreatmentsZ(
dframe = DT_pitcher2, # training data
varlist = colnames(DT_pitcher2) %>% .[. != "hitting_score1"], # input variables = all training data columns, except random
codeRestriction = c("clean", "isBAD", "lev"), # derived variables types (drop cat_P)
verbose = FALSE) # suppress messages
total_treated_2021_pitching <- vtreat::prepare(treat_plan_2021, DT_pitcher2)
#tr_treated = tr
#te_treated = te
dim(tr_treated_2021) #note there are dummies for each player and team[1] 3197 1416
The population used for Training should be indicative of Total Population
ggplot2::qplot(tr_treated_2021$Worth, main="Training Set") + geom_histogram(colour="black", fill="steelblue") + theme_bw()`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
#The skewness is actually a bit better than the overall data set
skewness(tr_treated_2021$Worth) [1] 0.1
To keep things simple with modeling, we’ll turn the training data
into simple input variables for caret::train, dropping the
response variable and converting the data frame to a matrix.
Documentation for this approach to XGboost can be found here.
Break the data set into x and y inputs with x being a matrix.
"_isBAD" is a category created by the Vtreat
package in case you want to identify rows
input_x <- as.matrix(((tr_treated_2021))%>%
select(-Worth) %>%
select(!ends_with ("_isBAD")))
input_y <- tr_treated_2021$WorthXGBoost with Default Hyperparameters:
The Variable Importance
(caret::varImp(xgb_base_2021, scale = F) from the caret
package shows the contribution of each variable to the initial model.
Since this is untuned, we can expect the percentage imporantance to
change as the models iterate through potential hyperparameters.
XGBoost documentation can be found for more general models here.
#Defaults for xgboost model
grid_default <- expand.grid(
nrounds = 100,
max_depth = 6,
eta = 0.3,
gamma = 0,
colsample_bytree = 1,
min_child_weight = 1,
subsample = 1
)
#This is a blank train_control set, this will be updated after
train_control <- caret::trainControl(
method = "none",
verboseIter = FALSE, # no training log
allowParallel = TRUE # FALSE for reproducible results
)
xgb_base_2021 <- caret::train(
x = input_x,
y = input_y,
trControl = train_control,
tuneGrid = grid_default,
method = "xgbTree",
verbose = TRUE
)
caret::varImp(xgb_base_2021, scale = F )xgbTree variable importance
only 20 most important variables shown (out of 774)
A tune grid allows us to test a large amount of hyper-parameters and
find the model with the lowest RMSE for predictions.
However, The more values you want to test and the greater the amount of
Cross-Fold Validations (method = "cv"), the greater the
computational time it will take. More information on the specific
parameters can be found here.
# maximum number of trees
nrounds <- 1000
# note to start nrounds from 200, as smaller learning rates result in errors so
# big with lower starting points that they'll mess the scales
tune_grid <- expand.grid(
nrounds = seq(from = 100, to = nrounds, by = 50),
eta = c(0.01, 0.025, 0.05, 0.075, 0.1),
max_depth = c(2, 4, 6, 8, 10),
gamma = 0,
colsample_bytree = 1,
min_child_weight = 1,
subsample = 1
)
tune_control <- caret::trainControl(
method = "cv", # cross-validation
number = 5, # with n folds
## Note this was # out in the original code
#index = createFolds(tr_treated$Id_clean), # fix the folds
verboseIter = FALSE, # no training log
allowParallel = FALSE # FALSE for reproducible results
)Running the initial tuning model
#Note I will be timing these runs to give an estimate on how long this model takes to run
start_time <- Sys.time()
xgb_tune_2021 <- caret::train(
x = input_x,
y = input_y,
trControl = tune_control,
tuneGrid = tune_grid,
method = "xgbTree",
verbose = FALSE
,verbosity = 0
)
end_time <- Sys.time()
end_time - start_timeTime difference of 21 mins
Tuning Plot and Variable Importance
varImp(xgb_tune_2021, scale = F ) xgbTree variable importance
only 20 most important variables shown (out of 766)
# helper function for the plots
tuneplot <- function(x, probs = .90) {
ggplot(x) +
coord_cartesian(ylim = c(quantile(x$results$RMSE, probs = probs), min(x$results$RMSE))) +
theme_bw()
}
tuneplot(xgb_tune_2021)After fixing the learning rate to the best tune from the previous iteration and we’ll also set maximum depth to 3 +-1 (or +2 if max_depth == 2) to experiment a bit around the suggested best tune in previous step. Then, well fix maximum depth and minimum child weight.
tune_grid2 <- expand.grid(
nrounds = seq(from = 50, to = nrounds, by = 50),
eta = xgb_tune_2021$bestTune$eta,
max_depth = ifelse(xgb_tune_2021$bestTune$max_depth == 2,
c(xgb_tune_2021$bestTune$max_depth:4),
xgb_tune_2021$bestTune$max_depth - 1:xgb_tune_2021$bestTune$max_depth + 1),
gamma = 0,
colsample_bytree = 1,
min_child_weight = c(1, 2, 3),
subsample = 1
)
xgb_tune2_2021 <- caret::train(
x = input_x,
y = input_y,
trControl = tune_control,
tuneGrid = tune_grid2,
method = "xgbTree",
verbose = TRUE
)
tuneplot(xgb_tune2_2021)
xgb_tune2_2021$bestTune
varImp(xgb_tune2_2021, scale = F ) xgbTree variable importance
only 20 most important variables shown (out of 766)
tune_grid3 <- expand.grid(
nrounds = seq(from = 50, to = nrounds, by = 50),
eta = xgb_tune_2021$bestTune$eta,
max_depth = xgb_tune2_2021$bestTune$max_depth,
gamma = 0,
colsample_bytree = c(0.4, 0.6, 0.8, 1.0),
min_child_weight = xgb_tune2_2021$bestTune$min_child_weight,
subsample = c(0.5, 0.75, 1.0)
)
xgb_tune3_2021 <- caret::train(
x = input_x,
y = input_y,
trControl = tune_control,
tuneGrid = tune_grid3,
method = "xgbTree",
verbose = TRUE
)
tuneplot(xgb_tune3_2021, probs = .95)
xgb_tune3_2021$bestTune
varImp(xgb_tune3_2021, scale = F ) xgbTree variable importance
only 20 most important variables shown (out of 766)
Next, we again pick the best values from previous step, and now will see whether changing the gamma has any effect on the model fit:
tune_grid4 <- expand.grid(
nrounds = seq(from = 50, to = nrounds, by = 50),
eta = xgb_tune_2021$bestTune$eta,
max_depth = xgb_tune2_2021$bestTune$max_depth,
gamma = c(0, 0.05,0.1, 0.2,0.4, 0.5, 0.7, 0.9, 1.0),
colsample_bytree = xgb_tune3_2021$bestTune$colsample_bytree,
min_child_weight = xgb_tune2_2021$bestTune$min_child_weight,
subsample = xgb_tune3_2021$bestTune$subsample
)
xgb_tune4_2021 <- caret::train(
x = input_x,
y = input_y,
trControl = tune_control,
tuneGrid = tune_grid4,
method = "xgbTree",
verbose = TRUE
)
tuneplot(xgb_tune4_2021)Warning: The shape palette can deal with a maximum of 6 discrete values because more than 6
becomes difficult to discriminate; you have 9. Consider specifying shapes manually if
you must have them.
Warning: Removed 60 rows containing missing values (geom_point).
xgb_tune4_2021$bestTune
varImp(xgb_tune4_2021, scale = F ) xgbTree variable importance
only 20 most important variables shown (out of 766)
Now, we have tuned the hyperparameters and can start reducing the learning rate to get to the final model:
start_time <- Sys.time()
tune_grid5 <- expand.grid(
nrounds = seq(from = 100, to = 10000, by = 75),
eta = c(0.01, 0.015, 0.025,0.035, 0.05,0.75, 0.1),
max_depth = xgb_tune2_2021$bestTune$max_depth,
gamma = xgb_tune4_2021$bestTune$gamma,
colsample_bytree = xgb_tune3_2021$bestTune$colsample_bytree,
min_child_weight = xgb_tune2_2021$bestTune$min_child_weight,
subsample = xgb_tune3_2021$bestTune$subsample
)
xgb_tune5_2021 <- caret::train(
x = input_x,
y = input_y,
trControl = tune_control,
tuneGrid = tune_grid5,
method = "xgbTree",
verbose = TRUE
)
#tuneplot(xgb_tune5_2021)
end_time <- Sys.time()
end_time - start_timeTime difference of 17 mins
xgb_tune5_2021$bestTune
varImp(xgb_tune5_2021, scale = F ) xgbTree variable importance
only 20 most important variables shown (out of 766)
(final_grid_2021 <- expand.grid(
nrounds = xgb_tune5_2021$bestTune$nrounds,
eta = xgb_tune5_2021$bestTune$eta,
max_depth = xgb_tune5_2021$bestTune$max_depth,
gamma = xgb_tune5_2021$bestTune$gamma,
colsample_bytree = xgb_tune5_2021$bestTune$colsample_bytree,
min_child_weight = xgb_tune5_2021$bestTune$min_child_weight,
subsample = xgb_tune5_2021$bestTune$subsample
))
(xgb_model_2021 <- caret::train(
x = input_x,
y = input_y,
trControl = train_control,
tuneGrid = final_grid_2021,
method = "xgbTree",
verbose = TRUE
))eXtreme Gradient Boosting
3197 samples
766 predictor
No pre-processing
Resampling: None
varImp(xgb_model_2021, scale = F ) xgbTree variable importance
only 20 most important variables shown (out of 766)
We don’t need to look too closely at are training data as Xgboost will heavily overfit the model based on that data. The more important part is how the model performs on in predicting our Test Sample that was not included.
y_pred_test <- predict(xgb_model_2021, data.matrix(te_treated_2021))
test_stats= cbind((te_treated_2021$Worth),y_pred_test)
test_statsR2 = cor(test_stats[,1],test_stats[,2])^2
print(test_statsR2)[1] 0.79
y_pred_train <- predict(xgb_model_2021, data.matrix(tr_treated_2021))
train_stats = cbind((tr_treated_2021$Worth),y_pred_train)
train_statsR2 = cor(train_stats[,1],train_stats[,2])^2
print(train_statsR2)[1] 0.94
#test dataset
x <- select(te_treated_2021, -Worth)
y <- (te_treated_2021$Worth)
(xgb_model_rmse <- ModelMetrics::rmse(y, predict(xgb_model_2021, newdata = x)))[1] 0.33
holdout_x <- select(tr_treated_2021, -Worth)
holdout_y <- tr_treated_2021$Worth
(xgb_model_rmse <- ModelMetrics::rmse(holdout_y, predict(xgb_model_2021, newdata = holdout_x)))[1] 0.18
ggplot2::ggplot() +
aes(x = test_stats[,1], y = test_stats[,2]) +
geom_jitter() +
xlab("Predicted Values") +
ylab("Actual Values") +
ggtitle("Results of Pitching Model on Test Data")+
theme(plot.title = element_text(hjust = 0.5,size = 22,color ="steel blue"))+
geom_smooth(method = "lm")`geom_smooth()` using formula 'y ~ x'
Now that we have an acceptable model, we can use it to create projections for how well we think players should do in 2022 based on their hitting statistics in 2021. First let’s reduce
Step 1: Only keep variables with high enough importance in model
vip(xgb_model_2021, num_features = 30) # 10 is the default, 30 gives a visual on the top 30 most important features of the model
unscalevi = vi(xgb_model_2021, method="model") #shows the numbers behind the plot
unscalevi$Importance_perc = with(unscalevi,Importance/sum(Importance)) #adds percentages
unscalevi # importance by variables
variables_to_keep_2021 = subset(unscalevi, Importance_perc > 0.0010) %>% select(Variable) #Keep Variables that explain at least a small amount [0.1%] of the model. This is a low threshold for inclusion ,but you can adjust this
variables_to_keep_2021b = t(variables_to_keep_2021)
variables_to_keep_2022 = colnames(row_to_names(variables_to_keep_2021b,row_number = 1))
tr_treated_2022 = tr_treated_2021 %>% select(Worth,one_of(variables_to_keep_2022),starts_with("Team_lev_x_")) #keep modeled important variables along with team indicator variables
te_treated_2022 = te_treated_2021 %>% select(Worth,one_of(variables_to_keep_2022),starts_with("Team_lev_x_"))
input_x_2022 = as.matrix(select(tr_treated_2022, -Worth))
input_y_2022 = tr_treated_2022$WorthStep 2: Re-fit model with reduced variable scope
Note from the best tune below the nrounds - is the max I
set above and eta is at the lowest possible value. This
could cause potential overfitting issues, but from our Actual
vs. Predicted Graph we know this not to be the case.
(final_grid_2021 <- expand.grid(
nrounds = xgb_tune5_2021$bestTune$nrounds,
eta = xgb_tune5_2021$bestTune$eta,
max_depth = xgb_tune5_2021$bestTune$max_depth,
gamma = xgb_tune5_2021$bestTune$gamma,
colsample_bytree = xgb_tune5_2021$bestTune$colsample_bytree,
min_child_weight = xgb_tune5_2021$bestTune$min_child_weight,
subsample = xgb_tune5_2021$bestTune$subsample
))
(xgb_model_2022 <- caret::train(
x = input_x_2022,
y = input_y_2022,
trControl = train_control,
tuneGrid = final_grid_2021,
method = "xgbTree",
verbose = TRUE
))eXtreme Gradient Boosting
3197 samples
93 predictor
No pre-processing
Resampling: None
vip(xgb_model_2022, num_features = 30)
unscalevi24 = vi(xgb_model_2022, method="model")
unscalevi24$Importance_perc = with(unscalevi24,Importance/sum(Importance))
unscalevi24
# Save work for later prediction
save(xgb_model_2022,file = '2022_Pitching6x6_Model.Rdata')
pitching6x6 = xgb_model_2022
pitchinginput6x6 = input_x_2022First let’s prepare a file for predicting based on our model object
variableslag6x= row_to_names(as.data.frame(t(variables_to_keep_2022)),row_number = 1) %>% select (starts_with("lag"))
variables_nolag6x = (owmr::remove_prefix(variableslag6x,"lag" , sep = "_"))
Data_Predict_2022a6x = total_treated_2021_pitching %>% select (one_of(colnames(variables_nolag6x)),Season,playerid)
colnames(Data_Predict_2022a6x) <- paste0("lag_", colnames(Data_Predict_2022a6x))
Data_Predict_2022b6x = total_treated_2021_pitching %>% select (one_of(colnames(variables_nolag6x)))
colnames(Data_Predict_2022b6x) = colnames(variableslag6x)
variables_to_keep_2022_nolag6x = total_treated_2021_pitching %>% select(one_of(variables_to_keep_2022),Season,playerid,starts_with("Team_lev_x_"))%>% select(-one_of(colnames(Data_Predict_2022b6x)))
Data_predict_20226x = sqldf(
"
select a.*,b.* from
Data_Predict_2022a6x a,
variables_to_keep_2022_nolag6x b
on b.playerid = a.lag_playerid
and b.Season = a.lag_Season
"
) %>% select(-lag_playerid,lag_Season) %>%
filter(Season == 2021) %>%
select(one_of(variables_to_keep_2022),starts_with("Team_lev_x_"))This is the raw prediction score per IP for each pitcher
pitching_predictions6x = as.data.frame(predict(xgb_model_2022,Data_predict_20226x))
names(pitching_predictions6x) = c("Predict_Score")
Data_predict_2022_w_Pitching_Predictions6x = cbind(Data_predict_2022,pitching_predictions6x) %>% select(playerid,Predict_Score)
head(Data_predict_2022_w_Pitching_Predictions6x)NADownloaded from FanGraphs here.
Latest_2022_pitchingdata_FP = read_csv("FanGraph_Fantasy_Baseball_Pitching.csv")Rows: 817 Columns: 27
-- Column specification -------------------------------------------------------------------------
Delimiter: ","
chr (3): Name, Team, playerid
dbl (24): GS, G, IP, W, L, QS, SV, HLD, H, ER, HR, SO, BB, WHIP, K/9, BB/9, ERA, FIP, WAR, RA...
i Use `spec()` to retrieve the full column specification for this data.
i Specify the column types or set `show_col_types = FALSE` to quiet this message.
Latest_2022_pitchingdata_FPNAAs you can see from the chart below there aren’t many elite pitchers in the 87+ Predict score range.
Pitching_Data_NonAdj_Projections6x = sqldf(
"
select a.*,b.Predict_Score
from Latest_2022_pitchingdata_FP a
left join
Data_predict_2022_w_Pitching_Predictions6x b
on a.playerid = b.playerid
"
) %>% filter(ADP<370 | is.na(Predict_Score)==F)
Pitching_Data_Adj_Projections6x =
Pitching_Data_NonAdj_Projections6x %>%
mutate(
Avg_IP = 60,
AdjPredict_Score_raw = ifelse(is.na(Predict_Score),NA,Predict_Score*(IP/Avg_IP)),
max_predscore= max(AdjPredict_Score_raw,na.rm = T),
AdjPredict_Score = ifelse (is.na(AdjPredict_Score_raw),NA,AdjPredict_Score_raw *100/max_predscore),
WAR_rank = order(order(rank(WAR,ties.method = 'average'),decreasing = TRUE)),
AdjPredict_Score_Rank = order(order(rank(AdjPredict_Score,ties.method = 'average'),decreasing = TRUE))-sum(is.na(AdjPredict_Score)),
Ranks_Above_ADP = ADP - AdjPredict_Score_Rank
) %>% select (Name,ADP,WAR, WAR_rank,AdjPredict_Score ,AdjPredict_Score_Rank,Ranks_Above_ADP)
ggplot2::qplot(Pitching_Data_Adj_Projections6x$AdjPredict_Score, main="Predictions") + geom_histogram(colour="black", fill="grey") + theme_bw()`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
AdjPredict_Score are normalized to 100
tableexport =
Pitching_Data_Adj_Projections6x %>%
arrange (ADP,WAR) %>%
kbl() %>%
kable_material(c("striped", "hover","condensed","responsive"),full_width = F,fixed_thead = T)
save_kable(tableexport,file = "Pitching6x6.html")
#tableexportThis is a better formatted Table
ft_dt <- Pitching_Data_Adj_Projections6x[1:nrow(Pitching_Data_Adj_Projections6x), 1:ncol(Pitching_Data_Adj_Projections6x)] %>%
filter(AdjPredict_Score_Rank>0)%>% arrange((AdjPredict_Score_Rank))
ft_dt$ADP <- color_tile("white", "red")(ft_dt$ADP)
ft_dt$WAR <- color_bar("lightblue")(ft_dt$WAR)
ft_dt$AdjPredict_Score<- color_bar("lightblue")(ft_dt$AdjPredict_Score)
ft_dt$WAR_Rank <- color_tile("green","orange")(ft_dt$WAR_rank)
ft_dt$Predict_Rank <- color_tile("green","orange")(ft_dt$AdjPredict_Score_Rank)
ft_dt$Ranks_Above_ADP <-
ifelse(
ft_dt$Ranks_Above_ADP < 0,
cell_spec(round(ft_dt$Ranks_Above_ADP,2), color = "red", italic = T),
cell_spec(round(ft_dt$Ranks_Above_ADP,2), color = "green", italic = T)
)
ft_dt2 <- ft_dt[c("Name", "ADP", "WAR", "AdjPredict_Score", "WAR_Rank","Predict_Rank","Ranks_Above_ADP")]
table_export =
kbl(ft_dt2, escape = F) %>%
kable_material(c("striped", "hover","condensed","responsive"),full_width = F,fixed_thead = T) %>% column_spec(6, width = "3cm") %>%
add_header_above(c(" ", "Scores" = 3, "Ranks" = 2," "))
save_kable(table_export,file = "Pitching6x6_updated.html")
table_export Scores |
Ranks |
|||||
|---|---|---|---|---|---|---|
| Name | ADP | WAR | AdjPredict_Score | WAR_Rank | Predict_Rank | Ranks_Above_ADP |
| Eduardo Rodriguez | 150.1 | 3.5 | 100.0 | 15 | 1 | 149.1 |
| Brady Singer | 492.4 | 2.2 | 97.1 | 53 | 2 | 490.4 |
| Dylan Cease | 81.2 | 3.3 | 95.4 | 20 | 3 | 78.2 |
| Josiah Gray | 290.7 | 1.6 | 93.1 | 89 | 4 | 286.7 |
| José Quintana | 575.5 | 1.0 | 92.8 | 143 | 5 | 570.5 |
| Shane Bieber | 31.2 | 4.4 | 91.9 | 4 | 6 | 25.2 |
| Tarik Skubal | 197.6 | 2.0 | 90.9 | 61 | 7 | 190.6 |
| Aaron Nola | 41.0 | 4.2 | 88.3 | 7 | 8 | 33 |
| Nick Pivetta | 350.8 | 1.7 | 87.5 | 86 | 9 | 341.8 |
| Alek Manoah | 93.0 | 2.8 | 87.5 | 33 | 10 | 83 |
| Shane McClanahan | 109.6 | 2.6 | 87.3 | 40 | 11 | 98.6 |
| Luis Castillo | 103.2 | 3.3 | 85.4 | 21 | 12 | 91.2 |
| Zac Gallen | 154.3 | 2.3 | 85.2 | 50 | 13 | 141.3 |
| Logan Webb | 69.9 | 3.7 | 84.7 | 11 | 14 | 55.9 |
| Tyler Mahle | 132.2 | 2.6 | 84.7 | 39 | 15 | 117.2 |
| Logan Gilbert | 161.8 | 2.2 | 84.6 | 52 | 16 | 145.8 |
| Corbin Burnes | 10.8 | 5.3 | 84.5 | 1 | 17 | -6.2 |
| Jon Gray | 236.9 | 2.3 | 84.4 | 51 | 18 | 218.9 |
| Brad Keller | 582.1 | 1.6 | 83.8 | 91 | 19 | 563.1 |
| Germán Márquez | 261.7 | 2.9 | 83.5 | 29 | 20 | 241.7 |
| Walker Buehler | 18.6 | 3.8 | 80.5 | 8 | 21 | -2.4 |
| Yusei Kikuchi | 301.3 | 1.7 | 80.2 | 83 | 22 | 279.3 |
| Jesús Luzardo | 289.5 | 0.8 | 79.8 | 158 | 23 | 266.5 |
| Gerrit Cole | 7.1 | 5.0 | 79.0 | 3 | 24 | -16.9 |
| Luis Garcia | 144.7 | 2.0 | 78.9 | 64 | 25 | 119.7 |
| Sean Manaea | 141.4 | 2.8 | 78.9 | 31 | 26 | 115.4 |
| Freddy Peralta | 54.0 | 3.6 | 78.8 | 12 | 27 | 27 |
| Trevor Rogers | 92.9 | 3.1 | 78.7 | 25 | 28 | 64.9 |
| Lucas Giolito | 44.2 | 3.7 | 77.9 | 10 | 29 | 15.2 |
| Michael Kopech | 161.1 | 2.5 | 77.9 | 43 | 30 | 131.1 |
| Ian Anderson | 151.1 | 2.1 | 77.0 | 56 | 31 | 120.1 |
| Tanner Houck | 206.4 | 2.4 | 76.5 | 47 | 32 | 174.4 |
| José Berríos | 77.5 | 3.2 | 76.4 | 23 | 33 | 44.5 |
| Andrew Heaney | 299.4 | 1.4 | 76.3 | 102 | 34 | 265.4 |
| Framber Valdez | 149.6 | 3.1 | 76.3 | 26 | 35 | 114.6 |
| Luis Patiño | 290.7 | 1.5 | 75.5 | 99 | 36 | 254.7 |
| Patrick Sandoval | 196.0 | 2.4 | 75.4 | 46 | 37 | 159 |
| Frankie Montas | 92.8 | 3.3 | 75.2 | 19 | 38 | 54.8 |
| Cole Irvin | 532.2 | 1.5 | 74.8 | 97 | 39 | 493.2 |
| Kris Bubic | 536.0 | 1.1 | 73.7 | 125 | 40 | 496 |
| Nathan Eovaldi | 135.1 | 3.6 | 73.5 | 13 | 41 | 94.1 |
| Julio Urías | 34.7 | 3.5 | 72.8 | 14 | 42 | -7.3 |
| Dane Dunning | 484.6 | 1.9 | 72.4 | 72 | 43 | 441.6 |
| Jordan Montgomery | 208.7 | 2.7 | 72.4 | 35 | 44 | 164.7 |
| Patrick Corbin | 456.0 | 1.6 | 72.2 | 95 | 45 | 411 |
| Steven Matz | 249.2 | 1.9 | 72.2 | 67 | 46 | 203.2 |
| Blake Snell | 113.4 | 2.4 | 71.9 | 49 | 47 | 66.4 |
| Zac Lowther | 999.0 | 0.8 | 71.9 | 159 | 48 | 951 |
| Aaron Civale | 269.5 | 1.5 | 71.8 | 96 | 49 | 220.5 |
| Zach Plesac | 346.6 | 1.5 | 71.6 | 100 | 50 | 296.6 |
| Bruce Zimmermann | 600.8 | 1.3 | 71.6 | 114 | 51 | 549.8 |
| Carlos Hernández | 412.5 | 1.2 | 71.5 | 121 | 52 | 360.5 |
| Mitch Keller | 531.5 | 1.2 | 71.5 | 123 | 53 | 478.5 |
| Kyle Hendricks | 279.8 | 1.7 | 70.6 | 79 | 54 | 225.8 |
| Cristian Javier | 284.0 | 1.2 | 70.6 | 118 | 55 | 229 |
| Sandy Alcantara | 43.4 | 3.3 | 70.4 | 18 | 56 | -12.6 |
| Bailey Ober | 261.3 | 2.2 | 70.2 | 55 | 57 | 204.3 |
| Shohei Ohtani | 9.2 | 2.8 | 70.1 | 32 | 58 | -48.8 |
| Kevin Gausman | 71.4 | 3.2 | 69.9 | 24 | 59 | 12.4 |
| Kyle Gibson | 393.9 | 1.9 | 69.4 | 71 | 60 | 333.9 |
| Robbie Ray | 49.9 | 3.0 | 69.4 | 27 | 61 | -11.1 |
| Michael Lorenzen | 543.3 | 0.6 | 69.3 | 203 | 62 | 481.3 |
| Yu Darvish | 100.3 | 2.7 | 69.3 | 34 | 63 | 37.3 |
| Matt Manning | 543.4 | 1.1 | 69.2 | 124 | 64 | 479.4 |
| Sonny Gray | 168.2 | 2.7 | 68.8 | 38 | 65 | 103.2 |
| Joe Ryan | 221.5 | 2.2 | 68.5 | 54 | 66 | 155.5 |
| Huascar Ynoa | 245.8 | 1.8 | 68.0 | 76 | 67 | 178.8 |
| Mike Minor | 532.2 | 2.0 | 67.8 | 63 | 68 | 464.2 |
| Brandon Woodruff | 21.2 | 4.2 | 67.2 | 6 | 69 | -47.8 |
| Triston McKenzie | 229.0 | 1.6 | 67.2 | 93 | 70 | 159 |
| JT Brubaker | 537.7 | 1.4 | 66.6 | 105 | 71 | 466.7 |
| Hyun Jin Ryu | 207.3 | 2.4 | 66.3 | 45 | 72 | 135.3 |
| Dylan Bundy | 498.5 | 1.3 | 66.2 | 109 | 73 | 425.5 |
| Kyle Freeland | 574.4 | 1.5 | 66.0 | 98 | 74 | 500.4 |
| Max Fried | 69.8 | 3.5 | 65.9 | 16 | 75 | -5.2 |
| Keegan Akin | 600.0 | 1.0 | 65.9 | 139 | 76 | 524 |
| Chris Flexen | 413.6 | 1.9 | 65.3 | 73 | 77 | 336.6 |
| Casey Mize | 279.4 | 1.7 | 65.0 | 84 | 78 | 201.4 |
| Ranger Suárez | 179.3 | 2.4 | 64.9 | 44 | 79 | 100.3 |
| Joe Musgrove | 70.6 | 3.2 | 64.7 | 22 | 80 | -9.4 |
| Spencer Howard | 575.8 | 0.9 | 64.4 | 150 | 81 | 494.8 |
| Reid Detmers | 427.4 | 1.1 | 64.2 | 134 | 82 | 345.4 |
| Drew Rasmussen | 282.4 | 1.6 | 63.5 | 88 | 83 | 199.4 |
| Antonio Senzatela | 585.0 | 2.0 | 63.1 | 62 | 84 | 501 |
| Taylor Hearn | 591.2 | 0.7 | 62.7 | 183 | 85 | 506.2 |
| Dallas Keuchel | 567.3 | 1.2 | 62.7 | 119 | 86 | 481.3 |
| Austin Gomber | 551.9 | 1.2 | 62.4 | 116 | 87 | 464.9 |
| Pablo López | 140.6 | 2.7 | 62.3 | 36 | 88 | 52.6 |
| Max Scherzer | 19.7 | 3.8 | 62.1 | 9 | 89 | -69.3 |
| Jordan Lyles | 578.9 | 0.6 | 61.5 | 196 | 90 | 488.9 |
| Ryan Yarbrough | 541.5 | 1.4 | 61.5 | 106 | 91 | 450.5 |
| Cal Quantrill | 267.3 | 1.7 | 61.0 | 82 | 92 | 175.3 |
| Merrill Kelly | 526.0 | 1.7 | 60.8 | 81 | 93 | 433 |
| José Suarez | 535.1 | 1.3 | 60.6 | 113 | 94 | 441.1 |
| Carlos Carrasco | 284.6 | 1.3 | 60.3 | 110 | 95 | 189.6 |
| Zack Wheeler | 31.0 | 4.4 | 60.3 | 5 | 96 | -65 |
| Alex Wood | 219.9 | 1.7 | 59.8 | 78 | 97 | 122.9 |
| Vladimir Gutierrez | 585.4 | 0.2 | 59.7 | 322 | 98 | 487.4 |
| Carlos Rodón | 110.2 | 2.9 | 59.5 | 28 | 99 | 11.2 |
| Eric Lauer | 306.3 | 1.4 | 59.5 | 103 | 100 | 206.3 |
| Chris Bassitt | 128.5 | 2.4 | 59.1 | 48 | 101 | 27.5 |
| Aaron Ashby | 264.1 | 1.5 | 58.9 | 101 | 102 | 162.1 |
| Lance Lynn | 70.0 | 3.4 | 58.9 | 17 | 103 | -33 |
| Alex Cobb | 242.9 | 1.9 | 58.8 | 70 | 104 | 138.9 |
| Tony Gonsolin | 300.6 | 0.9 | 58.7 | 148 | 105 | 195.6 |
| Elieser Hernandez | 339.6 | 1.0 | 58.4 | 145 | 106 | 233.6 |
| José Urquidy | 212.1 | 2.0 | 58.2 | 65 | 107 | 105.1 |
| James Kaprielian | 448.3 | 1.1 | 58.2 | 126 | 108 | 340.3 |
| Wil Crowe | 600.8 | 0.1 | 57.0 | 379 | 109 | 491.8 |
| Wade Miley | 502.0 | 1.2 | 56.9 | 120 | 110 | 392 |
| Chris Sale | 85.9 | 1.9 | 56.8 | 66 | 111 | -25.1 |
| Charlie Morton | 94.3 | 2.9 | 56.3 | 30 | 112 | -17.7 |
| Bryse Wilson | 600.5 | 0.5 | 56.3 | 223 | 113 | 487.5 |
| Zack Greinke | 312.8 | 1.6 | 56.1 | 90 | 114 | 198.8 |
| Marco Gonzales | 319.6 | 1.7 | 56.0 | 80 | 115 | 204.6 |
| Chris Paddack | 436.8 | 1.2 | 55.9 | 117 | 116 | 320.8 |
| Zach Davies | 595.9 | 0.2 | 55.7 | 343 | 117 | 478.9 |
| J.A. Happ | 597.0 | 0.6 | 55.2 | 199 | 118 | 479 |
| Erick Fedde | 589.7 | 0.6 | 54.9 | 188 | 119 | 470.7 |
| Daniel Bard | 579.3 | 0.4 | 54.8 | 266 | 120 | 459.3 |
| Marcus Stroman | 187.5 | 2.6 | 54.7 | 41 | 121 | 66.5 |
| Zach Eflin | 485.0 | 1.9 | 54.3 | 69 | 122 | 363 |
| Tylor Megill | 334.2 | 1.1 | 54.0 | 129 | 123 | 211.2 |
| Martín Pérez | 598.8 | 0.8 | 53.8 | 168 | 124 | 474.8 |
| Jack Flaherty | 115.4 | 1.6 | 53.7 | 87 | 125 | -9.6 |
| Michael Wacha | 549.7 | 0.9 | 53.6 | 149 | 126 | 423.7 |
| Adam Ottavino | 598.1 | 0.2 | 53.3 | 328 | 127 | 471.1 |
| Alec Mills | 594.1 | 0.6 | 53.3 | 211 | 128 | 466.1 |
| Daniel Lynch | 559.5 | 0.7 | 52.7 | 174 | 129 | 430.5 |
| Anthony DeSclafani | 212.6 | 1.8 | 52.7 | 77 | 130 | 82.6 |
| Jameson Taillon | 299.6 | 2.1 | 52.7 | 59 | 131 | 168.6 |
| Corey Kluber | 324.4 | 1.1 | 52.4 | 130 | 132 | 192.4 |
| Luke Weaver | 514.4 | 1.1 | 52.1 | 128 | 133 | 381.4 |
| Garrett Whitlock | 239.2 | 1.2 | 52.0 | 122 | 134 | 105.2 |
| José Alvarado | 587.6 | 0.5 | 51.8 | 237 | 135 | 452.6 |
| John Means | 217.1 | 2.7 | 50.8 | 37 | 136 | 81.1 |
| Tanner Rainey | 371.9 | 0.2 | 50.6 | 325 | 137 | 234.9 |
| Gregory Soto | 194.3 | 0.5 | 50.5 | 228 | 138 | 56.3 |
| Drew Smyly | 577.4 | 0.6 | 50.4 | 208 | 139 | 438.4 |
| Héctor Neris | 493.9 | 0.4 | 50.0 | 242 | 140 | 353.9 |
| Glenn Otto | 582.9 | 0.9 | 50.0 | 152 | 141 | 441.9 |
| Taijuan Walker | 414.5 | 0.6 | 49.6 | 185 | 142 | 272.5 |
| James Karinchak | 468.6 | 0.7 | 49.5 | 171 | 143 | 325.6 |
| Randy Dobnak | 600.4 | 0.8 | 49.4 | 162 | 144 | 456.4 |
| Madison Bumgarner | 507.1 | 1.1 | 49.4 | 131 | 145 | 362.1 |
| Nestor Cortes | 333.1 | 1.4 | 49.3 | 107 | 146 | 187.1 |
| Jacob deGrom | 19.7 | 5.1 | 49.0 | 2 | 147 | -127.3 |
| Adrian Houser | 465.0 | 1.4 | 49.0 | 104 | 148 | 317 |
| Kyle Finnegan | 351.5 | 0.2 | 48.5 | 336 | 149 | 202.5 |
| Edward Cabrera | 523.6 | 0.6 | 47.8 | 202 | 150 | 373.6 |
| Paul Sewald | 289.0 | 0.5 | 47.7 | 234 | 151 | 138 |
| Chad Green | 403.2 | 1.0 | 47.7 | 147 | 152 | 251.2 |
| Devin Williams | 287.1 | 1.1 | 47.6 | 133 | 153 | 134.1 |
| Scott Barlow | 159.3 | 0.9 | 47.5 | 155 | 154 | 5.3 |
| Clayton Kershaw | 149.4 | 2.5 | 47.4 | 42 | 155 | -5.6 |
| Pete Fairbanks | 517.3 | 0.6 | 47.4 | 194 | 156 | 361.3 |
| Jake Diekman | 585.9 | 0.5 | 47.2 | 232 | 157 | 428.9 |
| Amir Garrett | 586.6 | 0.2 | 47.1 | 333 | 158 | 428.6 |
| Carlos Estévez | 528.6 | 0.2 | 47.0 | 337 | 159 | 369.6 |
| Phil Maton | 600.4 | 0.4 | 46.6 | 248 | 160 | 440.4 |
| Stephen Strasburg | 294.0 | 1.3 | 46.5 | 111 | 161 | 133 |
| Tanner Scott | 599.0 | 0.7 | 46.4 | 182 | 162 | 437 |
| Lucas Sims | 243.6 | 0.7 | 46.1 | 180 | 163 | 80.6 |
| Tyler Alexander | 586.8 | 0.8 | 45.9 | 167 | 164 | 422.8 |
| Trevor May | 565.3 | 0.4 | 45.9 | 239 | 165 | 400.3 |
| Ryne Stanek | 598.8 | 0.2 | 45.8 | 330 | 166 | 432.8 |
| Alex Colomé | 378.0 | 0.1 | 45.8 | 387 | 167 | 211 |
| Adam Wainwright | 194.7 | 2.1 | 45.8 | 58 | 168 | 26.7 |
| Kyle Funkhouser | 999.0 | 0.1 | 45.8 | 386 | 169 | 830 |
| A.J. Alexy | 596.2 | 0.6 | 45.7 | 186 | 170 | 426.2 |
| Aroldis Chapman | 83.3 | 0.9 | 45.6 | 151 | 171 | -87.7 |
| Justin Steele | 598.7 | 0.4 | 45.6 | 245 | 172 | 426.7 |
| Aaron Bummer | 595.4 | 1.0 | 45.4 | 137 | 173 | 422.4 |
| Josh Fleming | 600.8 | 0.5 | 45.4 | 222 | 174 | 426.8 |
| Brad Boxberger | 588.3 | 0.2 | 45.4 | 331 | 175 | 413.3 |
| Mychal Givens | 549.7 | 0.1 | 45.2 | 419 | 176 | 373.7 |
| Zach Thompson | 546.8 | 1.0 | 45.2 | 146 | 177 | 369.8 |
| Bryan Shaw | 597.8 | -0.1 | 45.1 | 507 | 178 | 419.8 |
| Hansel Robles | 596.0 | -0.1 | 45.1 | 505 | 179 | 417 |
| Blake Treinen | 147.6 | 0.8 | 44.9 | 166 | 180 | -32.4 |
| Mike Mayers | 594.7 | 0.5 | 44.6 | 221 | 181 | 413.7 |
| Chris Stratton | 519.4 | 0.3 | 44.3 | 284 | 182 | 337.4 |
| Giovanny Gallegos | 113.5 | 1.0 | 44.3 | 140 | 183 | -69.5 |
| Miles Mikolas | 512.8 | 1.6 | 43.8 | 94 | 184 | 328.8 |
| Brent Suter | 587.6 | 0.4 | 43.8 | 268 | 185 | 402.6 |
| Garrett Crochet | 549.8 | 0.9 | 43.6 | 154 | 186 | 363.8 |
| Rich Hill | 477.4 | 0.7 | 43.6 | 173 | 187 | 290.4 |
| Dillon Peters | 600.7 | 0.0 | 43.4 | 421 | 188 | 412.7 |
| Joe Jiménez | 999.0 | 0.2 | 43.3 | 329 | 189 | 810 |
| Lou Trivino | 237.2 | 0.2 | 43.2 | 316 | 190 | 47.2 |
| Domingo Germán | 494.6 | 1.1 | 43.1 | 132 | 191 | 303.6 |
| Daniel Norris | 999.0 | 0.1 | 43.1 | 398 | 192 | 807 |
| Génesis Cabrera | 596.6 | 0.6 | 43.1 | 205 | 193 | 403.6 |
| Tyler Wells | 454.6 | 0.9 | 43.1 | 153 | 194 | 260.6 |
| David Peterson | 595.2 | 0.7 | 43.0 | 175 | 195 | 400.2 |
| Heath Hembree | 600.8 | 0.2 | 42.9 | 338 | 196 | 404.8 |
| Joely Rodríguez | 600.9 | 0.5 | 42.8 | 214 | 197 | 403.9 |
| Tyler Anderson | 564.5 | 0.7 | 42.7 | 172 | 198 | 366.5 |
| Matt Barnes | 245.2 | 0.8 | 42.7 | 164 | 199 | 46.2 |
| Jonathan Loáisiga | 393.7 | 1.0 | 42.6 | 142 | 200 | 193.7 |
| Johnny Cueto | 585.8 | 0.3 | 42.5 | 283 | 201 | 384.8 |
| Seth Lugo | 598.1 | 0.5 | 42.5 | 236 | 202 | 396.1 |
| Yimi García | 581.1 | 0.2 | 42.4 | 352 | 203 | 378.1 |
| José Cisnero | 999.0 | 0.3 | 42.2 | 281 | 204 | 795 |
| Austin Voth | 600.4 | 0.0 | 42.1 | 420 | 205 | 395.4 |
| Michael Fulmer | 347.0 | 0.6 | 42.1 | 192 | 206 | 141 |
| Rowan Wick | 302.0 | 0.4 | 42.0 | 249 | 207 | 95 |
| Camilo Doval | 159.8 | 0.5 | 41.9 | 229 | 208 | -48.2 |
| Cole Sulser | 427.2 | 0.7 | 41.6 | 177 | 209 | 218.2 |
| Justus Sheffield | 599.5 | 0.4 | 41.4 | 269 | 210 | 389.5 |
| J.B. Wendelken | 600.1 | 0.2 | 41.3 | 341 | 211 | 389.1 |
| Jordan Romano | 88.3 | 0.8 | 41.2 | 160 | 212 | -123.7 |
| David Price | 581.5 | 0.5 | 41.2 | 216 | 213 | 368.5 |
| Matt Wisler | 599.6 | 0.4 | 41.1 | 270 | 214 | 385.6 |
| Diego Castillo | 409.2 | 0.6 | 41.0 | 191 | 215 | 194.2 |
| Justin Dunn | 577.6 | 0.6 | 40.6 | 198 | 216 | 361.6 |
| Hirokazu Sawamura | 589.6 | 0.0 | 40.6 | 443 | 217 | 372.6 |
| Brad Hand | 520.0 | 0.2 | 40.2 | 351 | 218 | 302 |
| Emilio Pagán | 551.7 | 0.1 | 40.1 | 364 | 219 | 332.7 |
| Jaime Barría | 999.0 | 0.5 | 40.1 | 238 | 220 | 779 |
| Anthony Banda | 999.0 | -0.1 | 40.1 | 514 | 221 | 778 |
| Anthony Bender | 412.8 | 0.7 | 40.1 | 184 | 222 | 190.8 |
| Edwin Díaz | 63.5 | 1.1 | 39.9 | 135 | 223 | -159.5 |
| Michael Pineda | 465.2 | 1.4 | 39.9 | 108 | 224 | 241.2 |
| Tyler Rogers | 534.3 | 0.5 | 39.8 | 230 | 225 | 309.3 |
| Sam Hentges | 999.0 | 0.3 | 39.8 | 306 | 226 | 773 |
| Jeurys Familia | 597.5 | 0.3 | 39.8 | 305 | 227 | 370.5 |
| Griffin Canning | 594.2 | 0.5 | 39.8 | 213 | 228 | 366.2 |
| Lance McCullers Jr. | 260.0 | 1.7 | 39.8 | 85 | 229 | 31 |
| Daniel Hudson | 550.2 | 0.5 | 39.7 | 225 | 230 | 320.2 |
| Clay Holmes | 600.3 | 0.6 | 39.7 | 201 | 231 | 369.3 |
| Andrew Wantz | 999.0 | 0.4 | 39.7 | 262 | 232 | 767 |
| Taylor Rogers | 172.5 | 1.1 | 39.6 | 127 | 233 | -60.5 |
| Caleb Smith | 592.3 | 0.0 | 39.6 | 441 | 234 | 358.3 |
| Jorge Alcala | 459.0 | 0.6 | 39.6 | 209 | 235 | 224 |
| Luis Gil | 525.9 | 0.8 | 39.5 | 165 | 236 | 289.9 |
| Dylan Floro | 221.3 | 0.4 | 39.5 | 251 | 237 | -15.7 |
| Josh Staumont | 505.8 | 0.4 | 39.2 | 244 | 238 | 267.8 |
| Spencer Patton | 599.0 | 0.1 | 39.1 | 410 | 239 | 360 |
| Tyler Duffey | 577.8 | 0.4 | 39.0 | 260 | 240 | 337.8 |
| Jake Brentz | 600.8 | 0.3 | 39.0 | 301 | 241 | 359.8 |
| Josh Sborz | 600.9 | 0.3 | 38.9 | 290 | 242 | 358.9 |
| Raisel Iglesias | 47.6 | 1.0 | 38.8 | 138 | 243 | -195.4 |
| Chad Kuhl | 600.7 | 0.2 | 38.8 | 349 | 244 | 356.7 |
| Ryan Pressly | 64.3 | 1.0 | 38.8 | 136 | 245 | -180.7 |
| J.P. Feyereisen | 597.6 | 0.0 | 38.7 | 487 | 246 | 351.6 |
| Keegan Thompson | 999.0 | 0.0 | 38.3 | 429 | 247 | 752 |
| J.C. Mejía | 999.0 | 0.1 | 38.2 | 389 | 248 | 751 |
| Liam Hendriks | 32.0 | 1.6 | 38.1 | 92 | 249 | -217 |
| Sam Howard | 999.0 | 0.3 | 38.1 | 310 | 250 | 749 |
| Robert Stephenson | 590.5 | 0.0 | 38.0 | 466 | 251 | 339.5 |
| Tim Mayza | 599.3 | 0.6 | 37.9 | 197 | 252 | 347.3 |
| José Ureña | 999.0 | 0.0 | 37.8 | 467 | 253 | 746 |
| Craig Kimbrel | 164.4 | 0.7 | 37.6 | 176 | 254 | -89.6 |
| Jeff Hoffman | 999.0 | 0.0 | 37.5 | 426 | 255 | 744 |
| Garrett Richards | 598.7 | 0.4 | 37.4 | 272 | 256 | 342.7 |
| Anthony Misiewicz | 999.0 | 0.3 | 37.3 | 295 | 257 | 742 |
| Tony Santillan | 600.3 | 0.4 | 37.3 | 263 | 258 | 342.3 |
| Brusdar Graterol | 567.4 | 0.7 | 37.2 | 178 | 259 | 308.4 |
| Andrew Kittredge | 257.6 | 0.8 | 37.2 | 169 | 260 | -2.4 |
| A.J. Minter | 596.5 | 0.5 | 37.1 | 215 | 261 | 335.5 |
| Trevor Stephan | 999.0 | 0.1 | 37.1 | 368 | 262 | 737 |
| Ryan Helsley | 600.2 | 0.1 | 37.0 | 380 | 263 | 337.2 |
| Ryan Tepera | 581.3 | 0.4 | 36.8 | 246 | 264 | 317.3 |
| David Bednar | 190.8 | 0.9 | 36.8 | 156 | 265 | -74.2 |
| Jackson Kowar | 594.6 | 0.5 | 36.8 | 233 | 266 | 328.6 |
| Dean Kremer | 999.0 | 0.6 | 36.7 | 210 | 267 | 732 |
| Jake Odorizzi | 533.5 | 0.8 | 36.6 | 163 | 268 | 265.5 |
| Patrick Murphy | 999.0 | 0.4 | 36.6 | 254 | 269 | 730 |
| Yusmeiro Petit | 601.0 | -0.3 | 36.5 | 531 | 270 | 331 |
| Sergio Romo | 600.5 | 0.0 | 36.4 | 450 | 271 | 329.5 |
| Tyler Kinley | 999.0 | 0.0 | 36.3 | 433 | 272 | 727 |
| Kendall Graveman | 531.0 | 0.4 | 36.3 | 240 | 273 | 258 |
| Griffin Jax | 600.8 | 0.1 | 36.3 | 363 | 274 | 326.8 |
| Trevor Richards | 600.5 | 0.4 | 36.3 | 261 | 275 | 325.5 |
| Rafael Dolis | 999.0 | 0.0 | 36.2 | 434 | 276 | 723 |
| Sam Coonrod | 600.9 | 0.4 | 36.1 | 271 | 277 | 323.9 |
| Emmanuel Clase | 57.5 | 1.3 | 36.0 | 112 | 278 | -220.5 |
| Caleb Thielbar | 999.0 | 0.6 | 36.0 | 195 | 279 | 720 |
| Dinelson Lamet | 400.5 | 0.9 | 36.0 | 157 | 280 | 120.5 |
| Tyler Matzek | 573.2 | 0.7 | 36.0 | 181 | 281 | 292.2 |
| Corey Knebel | 151.3 | 0.6 | 35.9 | 204 | 282 | -130.7 |
| Josh Taylor | 999.0 | 0.5 | 35.4 | 217 | 283 | 716 |
| Paolo Espino | 599.2 | 0.2 | 35.2 | 327 | 284 | 315.2 |
| Nick Wittgren | 999.0 | 0.1 | 35.2 | 374 | 285 | 714 |
| Tim Hill | 999.0 | 0.3 | 35.1 | 293 | 286 | 713 |
| Wandy Peralta | 999.0 | 0.2 | 35.1 | 340 | 287 | 712 |
| Will Smith | 120.8 | 0.5 | 35.1 | 227 | 288 | -167.2 |
| Anthony Bass | 600.9 | 0.1 | 35.1 | 412 | 289 | 311.9 |
| Alex Vesia | 600.0 | 0.3 | 35.0 | 289 | 290 | 310 |
| Josh Hader | 30.5 | 1.3 | 35.0 | 115 | 291 | -260.5 |
| Archie Bradley | 600.7 | 0.2 | 35.0 | 348 | 292 | 308.7 |
| Eli Morgan | 600.5 | 0.2 | 34.6 | 346 | 293 | 307.5 |
| JT Chargois | 600.3 | 0.3 | 34.5 | 279 | 294 | 306.3 |
| Pierce Johnson | 433.3 | 0.6 | 34.4 | 200 | 295 | 138.3 |
| Duane Underwood Jr. | 999.0 | 0.1 | 34.4 | 417 | 296 | 703 |
| Ross Stripling | 583.7 | 0.4 | 34.3 | 256 | 297 | 286.7 |
| Brooks Raley | 600.9 | 0.3 | 34.0 | 296 | 298 | 302.9 |
| Miguel Castro | 600.9 | 0.1 | 33.8 | 372 | 299 | 301.9 |
| Lucas Gilbreath | 596.4 | 0.0 | 33.7 | 471 | 300 | 296.4 |
| José Quijada | 999.0 | 0.5 | 33.7 | 212 | 301 | 698 |
| Connor Brogdon | 600.4 | 0.4 | 33.6 | 252 | 302 | 298.4 |
| Nick Sandlin | 599.8 | 0.6 | 33.6 | 207 | 303 | 296.8 |
| Jhoulys Chacín | 999.0 | -0.4 | 33.5 | 533 | 304 | 695 |
| Jorge López | 599.9 | 0.4 | 33.4 | 265 | 305 | 294.9 |
| Dillon Tate | 600.9 | 0.4 | 33.3 | 264 | 306 | 294.9 |
| Jake Cousins | 600.1 | 0.5 | 33.3 | 226 | 307 | 293.1 |
| Luke Jackson | 598.1 | 0.4 | 33.1 | 267 | 308 | 290.1 |
| Adbert Alzolay | 444.0 | 0.7 | 33.0 | 179 | 309 | 135 |
| Kenley Jansen | 90.0 | 0.6 | 33.0 | 187 | 310 | -220 |
| Jarlín García | 600.8 | 0.1 | 32.9 | 411 | 311 | 289.8 |
| Darwinzon Hernandez | 999.0 | 0.2 | 32.7 | 324 | 312 | 687 |
| Trevor Williams | 601.0 | 0.2 | 32.5 | 326 | 313 | 288 |
| Rafael Montero | 999.0 | 0.1 | 32.5 | 394 | 314 | 685 |
| Drew Steckenrider | 401.5 | 0.3 | 32.5 | 294 | 315 | 86.5 |
| Austin Warren | 999.0 | 0.5 | 32.4 | 231 | 316 | 683 |
| Matthew Boyd | 591.0 | 1.0 | 32.3 | 144 | 317 | 274 |
| Collin McHugh | 545.5 | 0.6 | 32.3 | 189 | 318 | 227.5 |
| John King | 999.0 | 0.5 | 32.1 | 219 | 319 | 680 |
| Vince Velasquez | 599.4 | 0.3 | 32.1 | 308 | 320 | 279.4 |
| Alex Lange | 999.0 | 0.1 | 32.0 | 366 | 321 | 678 |
| Justin Wilson | 999.0 | 0.1 | 32.0 | 377 | 322 | 677 |
| Mark Melancon | 131.8 | 0.4 | 31.9 | 247 | 323 | -191.2 |
| Tyler Gilbert | 599.9 | 0.4 | 31.9 | 255 | 324 | 275.9 |
| Zach Pop | 999.0 | 0.2 | 31.9 | 345 | 325 | 674 |
| Sean Doolittle | 598.5 | 0.1 | 31.8 | 402 | 326 | 272.5 |
| Bailey Falter | 599.8 | 0.5 | 31.8 | 218 | 327 | 272.8 |
| Zack Littell | 599.3 | 0.1 | 31.6 | 367 | 328 | 271.3 |
| Kyle Zimmer | 999.0 | -0.2 | 31.3 | 528 | 329 | 670 |
| Steve Cishek | 595.3 | 0.0 | 31.3 | 439 | 330 | 265.3 |
| Ian Kennedy | 409.8 | -0.1 | 31.2 | 512 | 331 | 78.8 |
| Jake Woodford | 599.5 | 0.0 | 31.1 | 460 | 332 | 267.5 |
| Kwang Hyun Kim | 593.0 | 0.3 | 31.1 | 303 | 333 | 260 |
| Joe Smith | 999.0 | 0.1 | 31.0 | 361 | 334 | 665 |
| Ryan Hendrix | 999.0 | 0.0 | 31.0 | 468 | 335 | 664 |
| Cionel Pérez | 999.0 | 0.5 | 31.0 | 235 | 336 | 663 |
| Jeffrey Springs | 999.0 | 0.3 | 31.0 | 287 | 337 | 662 |
| Brett Martin | 999.0 | 0.4 | 30.9 | 275 | 338 | 661 |
| Max Kranick | 999.0 | 0.3 | 30.8 | 297 | 339 | 660 |
| Jakob Junis | 600.1 | 0.2 | 30.7 | 332 | 340 | 260.1 |
| Adam Morgan | 999.0 | 0.1 | 30.3 | 391 | 341 | 658 |
| Ryan Thompson | 999.0 | 0.3 | 30.3 | 278 | 342 | 657 |
| Taylor Widener | 600.5 | 0.0 | 30.2 | 424 | 343 | 257.5 |
| Jake McGee | 251.1 | 0.4 | 30.1 | 241 | 344 | -92.9 |
| Andrew Chafin | 587.9 | 0.6 | 29.9 | 206 | 345 | 242.9 |
| Blake Taylor | 999.0 | 0.2 | 29.8 | 353 | 346 | 653 |
| Dominic Leone | 600.8 | 0.1 | 29.7 | 371 | 347 | 253.8 |
| Phil Bickford | 600.9 | 0.4 | 29.6 | 258 | 348 | 252.9 |
| Johan Oviedo | 999.0 | 0.2 | 29.6 | 356 | 349 | 650 |
| Chris Martin | 600.3 | 0.4 | 29.6 | 277 | 350 | 250.3 |
| Dennis Santana | 999.0 | 0.0 | 29.4 | 442 | 351 | 648 |
| Craig Stammen | 599.4 | 0.4 | 29.4 | 259 | 352 | 247.4 |
| Tony Watson | 999.0 | 0.0 | 28.7 | 479 | 353 | 646 |
| Taylor Clarke | 999.0 | 0.0 | 28.6 | 437 | 354 | 645 |
| Luis Cessa | 588.8 | 0.3 | 28.5 | 299 | 355 | 233.8 |
| Austin Adams | 600.0 | 0.4 | 28.3 | 273 | 356 | 244 |
| Joe Barlow | 216.1 | 0.2 | 28.3 | 344 | 357 | -140.9 |
| Brett Anderson | 600.9 | 0.6 | 28.2 | 190 | 358 | 242.9 |
| Joe Kelly | 600.4 | 0.4 | 28.2 | 243 | 359 | 241.4 |
| Reynaldo López | 557.4 | 0.4 | 28.2 | 257 | 360 | 197.4 |
| Sean Newcomb | 600.1 | 0.1 | 28.1 | 400 | 361 | 239.1 |
| Austin Davis | 999.0 | 0.2 | 28.1 | 320 | 362 | 637 |
| Mike Foltynewicz | 600.4 | -0.1 | 28.0 | 511 | 363 | 237.4 |
| Sammy Long | 596.1 | 0.3 | 27.9 | 307 | 364 | 232.1 |
| Deolis Guerra | 599.9 | 0.2 | 27.9 | 342 | 365 | 234.9 |
| Albert Abreu | 999.0 | -0.1 | 27.9 | 496 | 366 | 633 |
| Josh Tomlin | 999.0 | -0.3 | 27.8 | 532 | 367 | 632 |
| Aaron Loup | 594.4 | 0.4 | 27.8 | 274 | 368 | 226.4 |
| Bryan Garcia | 999.0 | -0.2 | 27.7 | 530 | 369 | 630 |
| Joe Mantiply | 999.0 | 0.2 | 27.6 | 334 | 370 | 629 |
| Greg Holland | 600.2 | 0.0 | 27.5 | 473 | 371 | 229.2 |
| Tucker Davidson | 584.9 | 0.6 | 27.4 | 193 | 372 | 212.9 |
| Joe Ross | 599.6 | 0.7 | 27.3 | 170 | 373 | 226.6 |
| Alex Reyes | 395.7 | 0.2 | 27.2 | 335 | 374 | 21.7 |
| Alexander Wells | 999.0 | 0.4 | 26.8 | 276 | 375 | 624 |
| Wander Suero | 999.0 | 0.2 | 26.7 | 317 | 376 | 623 |
| Demarcus Evans | 600.6 | 0.0 | 26.7 | 472 | 377 | 223.6 |
| Michael King | 600.5 | 0.5 | 26.6 | 220 | 378 | 222.5 |
| Richard Rodríguez | 556.5 | 0.1 | 26.5 | 414 | 379 | 177.5 |
| Richard Bleier | 600.7 | 0.5 | 26.4 | 224 | 380 | 220.7 |
| Ryan Weathers | 600.8 | 0.3 | 26.4 | 300 | 381 | 219.8 |
| Yency Almonte | 999.0 | -0.2 | 26.3 | 524 | 382 | 617 |
| Matt Harvey | 999.0 | 0.3 | 26.1 | 286 | 383 | 616 |
| Logan Allen | 600.8 | 0.1 | 25.9 | 418 | 384 | 216.8 |
| Art Warren | 482.3 | 0.8 | 25.9 | 161 | 385 | 97.3 |
| Ralph Garza Jr. | 999.0 | -0.1 | 25.9 | 501 | 386 | 613 |
| Andrew Miller | 999.0 | -0.1 | 25.8 | 510 | 387 | 612 |
| Brad Brach | 999.0 | 0.0 | 25.4 | 436 | 388 | 611 |
| Nick Mears | 999.0 | 0.0 | 25.4 | 480 | 389 | 610 |
| Sean Reid-Foley | 999.0 | 0.0 | 25.3 | 438 | 390 | 609 |
| Domingo Tapia | 999.0 | 0.0 | 25.0 | 492 | 391 | 608 |
| Adam Cimber | 600.6 | 0.3 | 24.9 | 282 | 392 | 208.6 |
| Sean Poppen | 999.0 | 0.2 | 24.8 | 319 | 393 | 606 |
| Kolby Allard | 601.0 | 0.2 | 24.6 | 312 | 394 | 207 |
| Hunter Strickland | 599.9 | 0.0 | 24.6 | 423 | 395 | 204.9 |
| Brandon Kintzler | 999.0 | 0.0 | 24.5 | 464 | 396 | 603 |
| Matt Shoemaker | 999.0 | 0.0 | 24.5 | 457 | 397 | 602 |
| Ross Detwiler | 999.0 | 0.0 | 24.4 | 474 | 398 | 601 |
| Steven Brault | 600.9 | 0.0 | 24.2 | 432 | 399 | 201.9 |
| Steven Okert | 999.0 | 0.3 | 24.2 | 304 | 400 | 599 |
| Josh Rogers | 600.8 | -0.1 | 24.1 | 506 | 401 | 199.8 |
| Noé Ramirez | 600.9 | 0.1 | 24.1 | 390 | 402 | 198.9 |
| Jesse Chavez | 999.0 | 0.1 | 24.0 | 408 | 403 | 596 |
| Wily Peralta | 600.8 | 0.1 | 23.9 | 388 | 404 | 196.8 |
| Tyler Clippard | 600.8 | -0.2 | 23.8 | 529 | 405 | 195.8 |
| Jacob Webb | 999.0 | 0.0 | 23.7 | 447 | 406 | 593 |
| Drew Smith | 999.0 | 0.1 | 23.4 | 360 | 407 | 592 |
| Chi Chi González | 999.0 | 0.1 | 23.3 | 396 | 408 | 591 |
| Erik Swanson | 600.1 | 0.3 | 23.0 | 291 | 409 | 191.1 |
| Packy Naughton | 999.0 | 0.3 | 23.0 | 292 | 410 | 589 |
| Andres Machado | 999.0 | -0.1 | 22.8 | 513 | 411 | 588 |
| Derek Holland | 999.0 | -0.1 | 22.6 | 498 | 412 | 587 |
| Jay Jackson | 999.0 | 0.2 | 22.6 | 347 | 413 | 586 |
| T.J. McFarland | 999.0 | 0.1 | 22.4 | 378 | 414 | 585 |
| Mitch White | 562.7 | 0.3 | 22.3 | 288 | 415 | 147.7 |
| Buck Farmer | 999.0 | -0.2 | 22.2 | 519 | 416 | 583 |
| Blake Parker | 999.0 | 0.1 | 22.1 | 393 | 417 | 582 |
| Junior Guerra | 999.0 | 0.0 | 22.0 | 490 | 418 | 581 |
| Touki Toussaint | 598.6 | 0.1 | 22.0 | 369 | 419 | 179.6 |
| Ryan Borucki | 999.0 | 0.2 | 21.9 | 355 | 420 | 579 |
| Trevor Bauer | 208.4 | 1.0 | 21.6 | 141 | 421 | -212.6 |
| Jharel Cotton | 600.8 | 0.1 | 21.6 | 376 | 422 | 178.8 |
| Kodi Whitley | 999.0 | 0.2 | 21.6 | 350 | 423 | 576 |
| Bryan Abreu | 999.0 | 0.1 | 21.5 | 392 | 424 | 575 |
| Charlie Barnes | 999.0 | 0.2 | 21.5 | 339 | 425 | 574 |
| Michael Rucker | 999.0 | 0.0 | 21.5 | 427 | 426 | 573 |
| Ben Bowden | 999.0 | 0.1 | 21.4 | 395 | 427 | 572 |
| Kyle Muller | 590.8 | 0.3 | 21.3 | 302 | 428 | 162.8 |
| Nabil Crismatt | 999.0 | 0.1 | 21.1 | 403 | 429 | 570 |
| Brandon Bielak | 999.0 | 0.1 | 21.0 | 362 | 430 | 569 |
| Cody Ponce | 999.0 | 0.2 | 20.8 | 354 | 431 | 568 |
| Mason Thompson | 999.0 | 0.0 | 20.8 | 448 | 432 | 567 |
| Trevor Cahill | 999.0 | 0.2 | 20.0 | 313 | 433 | 566 |
| Alex Claudio | 999.0 | 0.0 | 19.9 | 463 | 434 | 565 |
| Carlos Martínez | 596.0 | 0.0 | 19.8 | 477 | 435 | 161 |
| Ryan Burr | 999.0 | 0.0 | 19.7 | 440 | 436 | 563 |
| Paul Campbell | 999.0 | -0.1 | 19.6 | 495 | 437 | 562 |
| Brandon Workman | 999.0 | -0.2 | 19.6 | 521 | 438 | 561 |
| Jake Arrieta | 999.0 | 0.0 | 19.5 | 481 | 439 | 560 |
| Joel Payamps | 999.0 | 0.3 | 19.0 | 285 | 440 | 559 |
| Trent Thornton | 999.0 | 0.1 | 18.9 | 401 | 441 | 558 |
| Jordan Holloway | 999.0 | -0.1 | 18.8 | 502 | 442 | 557 |
| Juan Minaya | 999.0 | 0.1 | 18.6 | 397 | 443 | 556 |
| Casey Sadler | 600.5 | 0.3 | 18.6 | 280 | 444 | 156.5 |
| Kyle McGowin | 999.0 | 0.2 | 18.4 | 321 | 445 | 554 |
| Matt Foster | 999.0 | 0.1 | 18.3 | 373 | 446 | 553 |
| Humberto Castellanos | 999.0 | 0.1 | 18.2 | 370 | 447 | 552 |
| Paul Blackburn | 999.0 | 0.2 | 18.0 | 315 | 448 | 551 |
| José Álvarez | 600.2 | 0.2 | 17.7 | 359 | 449 | 151.2 |
| Tyler Zuber | 999.0 | 0.0 | 17.6 | 462 | 450 | 549 |
| Yohan Ramirez | 599.8 | 0.1 | 17.4 | 413 | 451 | 148.8 |
| Jordan Sheffield | 999.0 | -0.2 | 17.4 | 520 | 452 | 547 |
| Miguel Sánchez | 999.0 | 0.0 | 17.3 | 484 | 453 | 546 |
| Jacob Barnes | 999.0 | 0.1 | 17.1 | 381 | 454 | 545 |
| Justin Garza | 999.0 | -0.2 | 16.7 | 523 | 455 | 544 |
| Drew Pomeranz | 582.3 | 0.1 | 16.7 | 383 | 456 | 126.3 |
| Phillips Valdez | 999.0 | -0.1 | 16.4 | 493 | 457 | 542 |
| Ryne Harper | 999.0 | 0.1 | 16.3 | 416 | 458 | 541 |
| Danny Coulombe | 999.0 | 0.1 | 16.2 | 382 | 459 | 540 |
| José Ruiz | 999.0 | 0.2 | 16.1 | 357 | 460 | 539 |
| JD Hammer | 999.0 | 0.0 | 16.0 | 483 | 461 | 538 |
| Michael Feliz | 999.0 | 0.0 | 15.9 | 425 | 462 | 537 |
| Ervin Santana | 999.0 | -0.5 | 15.8 | 534 | 463 | 536 |
| Tommy Nance | 999.0 | 0.1 | 15.6 | 385 | 464 | 535 |
| Rex Brothers | 999.0 | 0.0 | 15.6 | 461 | 465 | 534 |
| Junior Fernández | 999.0 | 0.1 | 15.5 | 415 | 466 | 533 |
| Anthony Castro | 999.0 | 0.1 | 15.2 | 375 | 467 | 532 |
| Dan Winkler | 999.0 | -0.1 | 15.1 | 515 | 468 | 531 |
| Chasen Shreve | 999.0 | -0.1 | 15.0 | 509 | 469 | 530 |
| Héctor Santiago | 999.0 | -0.2 | 14.7 | 525 | 470 | 529 |
| Brett de Geus | 999.0 | 0.0 | 14.6 | 475 | 471 | 528 |
| Hoby Milner | 999.0 | 0.1 | 14.3 | 405 | 472 | 527 |
| Wade LeBlanc | 999.0 | 0.2 | 14.1 | 358 | 473 | 526 |
| Matt Peacock | 999.0 | 0.0 | 14.1 | 488 | 474 | 525 |
| Shane Greene | 999.0 | -0.1 | 13.7 | 499 | 475 | 524 |
| Nick Neidert | 999.0 | -0.2 | 13.7 | 517 | 476 | 523 |
| Aaron Sanchez | 600.6 | 0.0 | 13.6 | 451 | 477 | 123.6 |
| Matt Moore | 999.0 | -0.1 | 13.5 | 503 | 478 | 521 |
| Anthony Kay | 999.0 | 0.0 | 13.4 | 422 | 479 | 520 |
| Sean Guenther | 999.0 | 0.2 | 13.4 | 323 | 480 | 519 |
| Victor González | 999.0 | 0.1 | 13.3 | 365 | 481 | 518 |
| Keynan Middleton | 999.0 | -0.1 | 13.1 | 500 | 482 | 517 |
| Humberto Mejía | 999.0 | 0.0 | 13.1 | 453 | 483 | 516 |
| Sam Selman | 999.0 | 0.0 | 12.9 | 444 | 484 | 515 |
| Danny Duffy | 587.9 | 0.2 | 12.3 | 318 | 485 | 102.9 |
| Cody Poteet | 999.0 | 0.1 | 12.1 | 407 | 486 | 513 |
| Chris Mazza | 999.0 | 0.3 | 11.9 | 309 | 487 | 512 |
| Kohei Arihara | 999.0 | 0.0 | 11.9 | 449 | 488 | 511 |
| Yennsy Díaz | 999.0 | -0.1 | 11.9 | 516 | 489 | 510 |
| Braxton Garrett | 999.0 | 0.0 | 11.4 | 428 | 490 | 509 |
| Louis Head | 600.5 | 0.3 | 11.4 | 311 | 491 | 109.5 |
| Ashton Goudeau | 999.0 | -0.2 | 11.4 | 527 | 492 | 507 |
| Chase Anderson | 999.0 | 0.0 | 11.2 | 491 | 493 | 506 |
| Cam Bedrosian | 999.0 | 0.0 | 10.7 | 458 | 494 | 505 |
| César Valdez | 600.3 | 0.0 | 10.6 | 431 | 495 | 105.3 |
| Sam Clay | 999.0 | 0.0 | 10.3 | 430 | 496 | 503 |
| Dustin May | 559.5 | 0.3 | 10.1 | 298 | 497 | 62.5 |
| Daniel Ponce de Leon | 600.7 | 0.0 | 9.6 | 456 | 498 | 102.7 |
| Dillon Maples | 999.0 | 0.1 | 9.3 | 409 | 499 | 500 |
| Erasmo Ramírez | 999.0 | -0.2 | 9.2 | 526 | 500 | 499 |
| Caleb Baragar | 999.0 | -0.2 | 9.2 | 522 | 501 | 498 |
| Robert Gsellman | 999.0 | -0.2 | 8.6 | 518 | 502 | 497 |
| Marcos Diplán | 999.0 | 0.0 | 8.6 | 459 | 503 | 496 |
| Miguel Diaz | 999.0 | -0.1 | 8.5 | 494 | 504 | 495 |
| Edwin Uceta | 999.0 | 0.0 | 8.1 | 455 | 505 | 494 |
| Enyel De Los Santos | 999.0 | 0.1 | 7.6 | 404 | 506 | 493 |
| Wes Benjamin | 999.0 | -0.1 | 7.4 | 504 | 507 | 492 |
| Thomas Eshelman | 999.0 | 0.0 | 7.3 | 476 | 508 | 491 |
| Reiss Knehr | 999.0 | 0.0 | 7.3 | 446 | 509 | 490 |
| Jake Faria | 999.0 | 0.0 | 6.9 | 469 | 510 | 489 |
| Luke Farrell | 999.0 | 0.0 | 6.8 | 489 | 511 | 488 |
| Tayler Saucedo | 999.0 | 0.1 | 6.7 | 399 | 512 | 487 |
| Robert Dugger | 999.0 | 0.0 | 6.2 | 478 | 513 | 486 |
| Shaun Anderson | 999.0 | 0.0 | 6.2 | 445 | 514 | 485 |
| Adrian Sampson | 999.0 | -0.1 | 6.1 | 508 | 515 | 484 |
| Drew Hutchison | 999.0 | -0.1 | 5.7 | 497 | 516 | 483 |
| Kyle Crick | 999.0 | 0.0 | 5.5 | 465 | 517 | 482 |
| Shawn Armstrong | 999.0 | 0.0 | 5.4 | 454 | 518 | 481 |
| Edgar Santana | 999.0 | 0.0 | 5.3 | 452 | 519 | 480 |
| Kevin Ginkel | 999.0 | 0.0 | 5.1 | 470 | 520 | 479 |
| Sean Nolin | 999.0 | 0.0 | 5.0 | 485 | 521 | 478 |
| Carson Fulmer | 999.0 | 0.0 | 4.8 | 482 | 522 | 477 |
| Tyler Glasnow | 598.8 | 0.2 | 4.6 | 314 | 523 | 75.8 |
| Daniel Castano | 999.0 | 0.0 | 4.0 | 486 | 524 | 475 |
| John Gant | 600.8 | 0.0 | 4.0 | 435 | 525 | 75.8 |
| Kenta Maeda | 600.7 | 0.1 | 3.3 | 384 | 526 | 74.7 |
| Chris Ellis | 600.8 | 0.1 | 3.0 | 406 | 527 | 73.8 |
NA
NA
NA
NA
NA
NA