#Load Data
ssmlb <- read.csv("MLB Players-hittingstats-ss.csv")
# The first 6 rows
head(ssmlb)
str(ssmlb)
'data.frame': 47 obs. of 17 variables:
$ Player : chr "Trea Turner" "Bo Bichette" "Amed Rosario" "Xander Bogaerts" ...
$ Pos : chr "SS" "SS" "SS" "SS" ...
$ Team : chr "LAD" "TOR" "CLE" "BOS" ...
$ GS : int 160 158 151 148 161 133 148 151 129 138 ...
$ AB : int 652 652 637 557 630 522 591 593 481 563 ...
$ H : int 194 189 180 171 170 152 150 145 135 134 ...
$ X2B : int 39 43 26 38 25 24 31 24 22 31 ...
$ X3B : int 4 1 9 0 5 1 6 1 5 0 ...
$ HR : int 21 24 11 15 26 22 20 33 10 31 ...
$ RBI : int 100 93 71 73 107 64 80 83 55 98 ...
$ AVG : num 0.298 0.29 0.283 0.307 0.27 0.291 0.254 0.245 0.281 0.238 ...
$ OBP : num 0.343 0.333 0.312 0.377 0.339 0.366 0.294 0.317 0.327 0.298 ...
$ SLG : num 0.466 0.469 0.403 0.456 0.449 0.467 0.428 0.455 0.41 0.458 ...
$ OPS : num 0.809 0.802 0.715 0.833 0.788 0.834 0.722 0.772 0.736 0.756 ...
$ WAR : num 4.84 3.44 3.95 5.42 5.4 5.55 1.05 4.04 4.5 4.42 ...
$ Cash2023: chr "$27,272,727 " "$6,100,000 " "$7,800,000 " "$30,000,000 " ...
$ Age : int 29 24 26 29 28 27 22 28 25 26 ...
#Inspect the Data
class(ssmlb$Cash2023)
[1] "character"
#Clean the Data
# Removing the “$” , extra space and commas from salary, converting it to a number.
ssmlb$Salary <- gsub("\\$", "", ssmlb$Cash2023)
ssmlb$Salary <- gsub(",", "", ssmlb$Salary)
ssmlb$Salary <- trimws(ssmlb$Salary)
ssmlb$Salary <- as.numeric(ssmlb$Salary)
ssmlb$Salary_M <- ssmlb$Salary / 1000000
# VERIFY changes have been made:
class(ssmlb$Salary_M)
[1] "numeric"
#Checking for missing value
colSums(is.na (ssmlb))
Player Pos Team GS AB H X2B X3B
0 0 0 0 0 0 0 0
HR RBI AVG OBP SLG OPS WAR Cash2023
0 0 0 0 0 0 0 0
Age Salary Salary_M
0 0 0
#Check Duplicate records
sum(duplicated(ssmlb))
[1] 0
summary(ssmlb)
Player Pos Team GS
Length :47 Length :47 Length :47 Min. : 7.00
N.unique :47 N.unique : 1 N.unique :29 1st Qu.: 55.50
N.blank : 0 N.blank : 0 N.blank : 0 Median :100.00
Min.nchar: 9 Min.nchar: 2 Min.nchar: 2 Mean : 96.36
Max.nchar:18 Max.nchar: 2 Max.nchar: 3 3rd Qu.:142.00
Max. :161.00
AB H X2B X3B
Min. : 29.0 Min. : 7.00 Min. : 1.00 Min. :0.000
1st Qu.:204.5 1st Qu.: 41.00 1st Qu.: 8.00 1st Qu.:0.000
Median :365.0 Median : 88.00 Median :19.00 Median :2.000
Mean :363.7 Mean : 91.34 Mean :17.45 Mean :1.936
3rd Qu.:521.5 3rd Qu.:132.50 3rd Qu.:25.00 3rd Qu.:3.000
Max. :652.0 Max. :194.00 Max. :43.00 Max. :9.000
HR RBI AVG OBP
Min. : 1.000 Min. : 2.00 Min. :0.1570 Min. :0.2360
1st Qu.: 4.000 1st Qu.: 18.50 1st Qu.:0.2165 1st Qu.:0.2815
Median : 7.000 Median : 36.00 Median :0.2450 Median :0.2990
Mean : 9.915 Mean : 42.32 Mean :0.2449 Mean :0.3040
3rd Qu.:14.500 3rd Qu.: 63.50 3rd Qu.:0.2705 3rd Qu.:0.3250
Max. :33.000 Max. :107.00 Max. :0.3450 Max. :0.4410
SLG OPS WAR Cash2023
Min. :0.2620 Min. :0.5300 Min. :-0.980 Length :47
1st Qu.:0.3265 1st Qu.:0.6265 1st Qu.: 0.255 N.unique :45
Median :0.3860 Median :0.6910 Median : 1.150 N.blank : 0
Mean :0.3830 Mean :0.6870 Mean : 1.819 Min.nchar: 9
3rd Qu.:0.4265 3rd Qu.:0.7360 3rd Qu.: 3.115 Max.nchar:12
Max. :0.5860 Max. :1.0270 Max. : 5.550
Age Salary Salary_M
Min. :20.00 Min. : 410326 Min. : 0.4103
1st Qu.:24.00 1st Qu.: 724600 1st Qu.: 0.7246
Median :26.00 Median : 2000000 Median : 2.0000
Mean :26.21 Mean : 6855709 Mean : 6.8557
3rd Qu.:28.00 3rd Qu.: 8250000 3rd Qu.: 8.2500
Max. :35.00 Max. :36000000 Max. :36.0000
#Exploratory Data
#Correlations: created temporary numeric data-set for correlations
ssmlb_numeric <- ssmlb[sapply(ssmlb, is.numeric)]
ssmlb_numeric$Salary <- NULL
cor(ssmlb_numeric)
GS AB H X2B X3B HR
GS 1.0000000 0.9878832 0.9387030 0.8804607 0.366752978 0.7339877
AB 0.9878832 1.0000000 0.9741364 0.9156261 0.389106791 0.7840134
H 0.9387030 0.9741364 1.0000000 0.9356879 0.375379829 0.7724508
X2B 0.8804607 0.9156261 0.9356879 1.0000000 0.293089007 0.7399494
X3B 0.3667530 0.3891068 0.3753798 0.2930890 1.000000000 0.1576920
HR 0.7339877 0.7840134 0.7724508 0.7399494 0.157692045 1.0000000
RBI 0.8833421 0.9243508 0.9298298 0.8896238 0.315943566 0.8973054
AVG 0.2527911 0.3350714 0.4999607 0.4540903 0.115910827 0.2808246
OBP 0.1430023 0.1935521 0.3283211 0.2978383 0.001986825 0.2055263
SLG 0.1628489 0.2577958 0.3830350 0.3966754 0.102071214 0.5288822
OPS 0.1672546 0.2520635 0.3908039 0.3880660 0.069776549 0.4423801
WAR 0.7585507 0.7838553 0.8122353 0.7383154 0.308012465 0.7154940
Age 0.2663626 0.2643532 0.2483782 0.2137952 -0.098017716 0.1988217
Salary_M 0.4710708 0.5099290 0.5628422 0.4634702 0.030049924 0.6053461
RBI AVG OBP SLG OPS WAR
GS 0.8833421 0.2527911 0.143002251 0.1628489 0.16725465 0.7585507
AB 0.9243508 0.3350714 0.193552094 0.2577958 0.25206353 0.7838553
H 0.9298298 0.4999607 0.328321103 0.3830350 0.39080388 0.8122353
X2B 0.8896238 0.4540903 0.297838268 0.3966754 0.38806597 0.7383154
X3B 0.3159436 0.1159108 0.001986825 0.1020712 0.06977655 0.3080125
HR 0.8973054 0.2808246 0.205526332 0.5288822 0.44238007 0.7154940
RBI 1.0000000 0.3961871 0.285046646 0.4542913 0.42255309 0.7653890
AVG 0.3961871 1.0000000 0.807340495 0.7975364 0.86254468 0.4335819
OBP 0.2850466 0.8073405 1.000000000 0.7032172 0.87380311 0.3843565
SLG 0.4542913 0.7975364 0.703217214 1.0000000 0.96018521 0.4288262
OPS 0.4225531 0.8625447 0.873803113 0.9601852 1.00000000 0.4439624
WAR 0.7653890 0.4335819 0.384356543 0.4288262 0.44396237 1.0000000
Age 0.2358260 0.1043517 0.054119374 0.1016015 0.09065536 0.1841738
Salary_M 0.5789837 0.3434524 0.373311756 0.3875104 0.41241558 0.6341681
Age Salary_M
GS 0.26636259 0.47107079
AB 0.26435320 0.50992895
H 0.24837822 0.56284220
X2B 0.21379517 0.46347021
X3B -0.09801772 0.03004992
HR 0.19882166 0.60534606
RBI 0.23582598 0.57898374
AVG 0.10435169 0.34345236
OBP 0.05411937 0.37331176
SLG 0.10160148 0.38751040
OPS 0.09065536 0.41241558
WAR 0.18417379 0.63416813
Age 1.00000000 0.44225191
Salary_M 0.44225191 1.00000000
#Salary vs HR 0.605, Salary vs WAR 0.634, Salary vs RBI 0.579, Salary vs Hits 0.563, AVG and OPS 0.863, SLG and OPS 0.960 #The correlation matrix to identify which performance statistics were most closely related to player salary. WAR showed the strongest relationship with salary, followed by home runs and RBIs.
#The highest-paid shortstops
ssmlb[order(-ssmlb$Salary_M),
c("Player","Salary_M","WAR")]
#Most of the highest-paid players also have high WAR, suggesting teams pay more for players who contribute more wins. However, Nick Ahmed earns over $10 million but has a negative WAR.
# Ranking players by WAR
ssmlb[order(-ssmlb$WAR),
c("Player","WAR","Salary_M")]
#The highest-performing players are not always the most expensive.Jeremy Peña has a WAR of 4.64 while earning less than $1 million and Nico Hoerner also provides excellent value.
ssmlb$WAR_per_Million <- ssmlb$WAR / ssmlb$Salary_M
ssmlb[order(-ssmlb$WAR_per_Million),
c("Player", "WAR", "Salary_M", "WAR_per_Million")]