Introduction

This activity uses the official baseball.csv file from Canvas. The dataset contains team-level baseball statistics such as runs scored, runs allowed, wins, on-base percentage, slugging percentage, batting average, games played, and playoff results.

The goal is to practice importing a CSV file, exploring a data frame, creating new variables, producing basic visualizations, and building a simple linear regression model to predict wins.

1. Import the Baseball Dataset

Make sure baseball.csv is uploaded to the same Posit/RStudio folder as this R Markdown file.

baseball <- read.csv("baseball.csv")

head(baseball)
##   Team League Year  RS  RA  W   OBP   SLG    BA Playoffs RankSeason
## 1  ARI     NL 2012 734 688 81 0.328 0.418 0.259        0         NA
## 2  ATL     NL 2012 700 600 94 0.320 0.389 0.247        1          4
## 3  BAL     AL 2012 712 705 93 0.311 0.417 0.247        1          5
## 4  BOS     AL 2012 734 806 69 0.315 0.415 0.260        0         NA
## 5  CHC     NL 2012 613 759 61 0.302 0.378 0.240        0         NA
## 6  CHW     AL 2012 748 676 85 0.318 0.422 0.255        0         NA
##   RankPlayoffs   G  OOBP  OSLG
## 1           NA 162 0.317 0.415
## 2            5 162 0.306 0.378
## 3            4 162 0.315 0.403
## 4           NA 162 0.331 0.428
## 5           NA 162 0.335 0.424
## 6           NA 162 0.319 0.405

2. Explore the Dataset

# View the structure of the dataset
str(baseball)
## 'data.frame':    1232 obs. of  15 variables:
##  $ Team        : chr  "ARI" "ATL" "BAL" "BOS" ...
##  $ League      : chr  "NL" "NL" "AL" "AL" ...
##  $ Year        : int  2012 2012 2012 2012 2012 2012 2012 2012 2012 2012 ...
##  $ RS          : int  734 700 712 734 613 748 669 667 758 726 ...
##  $ RA          : int  688 600 705 806 759 676 588 845 890 670 ...
##  $ W           : int  81 94 93 69 61 85 97 68 64 88 ...
##  $ OBP         : num  0.328 0.32 0.311 0.315 0.302 0.318 0.315 0.324 0.33 0.335 ...
##  $ SLG         : num  0.418 0.389 0.417 0.415 0.378 0.422 0.411 0.381 0.436 0.422 ...
##  $ BA          : num  0.259 0.247 0.247 0.26 0.24 0.255 0.251 0.251 0.274 0.268 ...
##  $ Playoffs    : int  0 1 1 0 0 0 1 0 0 1 ...
##  $ RankSeason  : int  NA 4 5 NA NA NA 2 NA NA 6 ...
##  $ RankPlayoffs: int  NA 5 4 NA NA NA 4 NA NA 2 ...
##  $ G           : int  162 162 162 162 162 162 162 162 162 162 ...
##  $ OOBP        : num  0.317 0.306 0.315 0.331 0.335 0.319 0.305 0.336 0.357 0.314 ...
##  $ OSLG        : num  0.415 0.378 0.403 0.428 0.424 0.405 0.39 0.43 0.47 0.402 ...
# View the column names
names(baseball)
##  [1] "Team"         "League"       "Year"         "RS"           "RA"          
##  [6] "W"            "OBP"          "SLG"          "BA"           "Playoffs"    
## [11] "RankSeason"   "RankPlayoffs" "G"            "OOBP"         "OSLG"
# View summary statistics
summary(baseball)
##         Team            League          Year            RS        
##  Length   :1232   Length   :1232   Min.   :1962   Min.   : 463.0  
##  N.unique :  39   N.unique :   2   1st Qu.:1977   1st Qu.: 652.0  
##  N.blank  :   0   N.blank  :   0   Median :1989   Median : 711.0  
##  Min.nchar:   3   Min.nchar:   2   Mean   :1989   Mean   : 715.1  
##  Max.nchar:   3   Max.nchar:   2   3rd Qu.:2002   3rd Qu.: 775.0  
##                                    Max.   :2012   Max.   :1009.0  
##                                                                   
##        RA               W              OBP              SLG        
##  Min.   : 472.0   Min.   : 40.0   Min.   :0.2770   Min.   :0.3010  
##  1st Qu.: 649.8   1st Qu.: 73.0   1st Qu.:0.3170   1st Qu.:0.3750  
##  Median : 709.0   Median : 81.0   Median :0.3260   Median :0.3960  
##  Mean   : 715.1   Mean   : 80.9   Mean   :0.3263   Mean   :0.3973  
##  3rd Qu.: 774.2   3rd Qu.: 89.0   3rd Qu.:0.3370   3rd Qu.:0.4210  
##  Max.   :1103.0   Max.   :116.0   Max.   :0.3730   Max.   :0.4910  
##                                                                    
##        BA            Playoffs        RankSeason     RankPlayoffs  
##  Min.   :0.2140   Min.   :0.0000   Min.   :1.000   Min.   :1.000  
##  1st Qu.:0.2510   1st Qu.:0.0000   1st Qu.:2.000   1st Qu.:2.000  
##  Median :0.2600   Median :0.0000   Median :3.000   Median :3.000  
##  Mean   :0.2593   Mean   :0.1981   Mean   :3.123   Mean   :2.717  
##  3rd Qu.:0.2680   3rd Qu.:0.0000   3rd Qu.:4.000   3rd Qu.:4.000  
##  Max.   :0.2940   Max.   :1.0000   Max.   :8.000   Max.   :5.000  
##                                    NAs    :988     NAs    :988    
##        G              OOBP             OSLG       
##  Min.   :158.0   Min.   :0.2940   Min.   :0.3460  
##  1st Qu.:162.0   1st Qu.:0.3210   1st Qu.:0.4010  
##  Median :162.0   Median :0.3310   Median :0.4190  
##  Mean   :161.9   Mean   :0.3323   Mean   :0.4197  
##  3rd Qu.:162.0   3rd Qu.:0.3430   3rd Qu.:0.4380  
##  Max.   :165.0   Max.   :0.3840   Max.   :0.4990  
##                  NAs    :812      NAs    :812

The dataset includes the following important variables:

3. Create Run Differential

Run differential is calculated as runs scored minus runs allowed.

\[ Run\ Differential = RS - RA \]

baseball$Run_Differential <- baseball$RS - baseball$RA

head(baseball[, c("Team", "Year", "RS", "RA", "Run_Differential", "W")])
##   Team Year  RS  RA Run_Differential  W
## 1  ARI 2012 734 688               46 81
## 2  ATL 2012 700 600              100 94
## 3  BAL 2012 712 705                7 93
## 4  BOS 2012 734 806              -72 69
## 5  CHC 2012 613 759             -146 61
## 6  CHW 2012 748 676               72 85

4. Create Winning Percentage

Winning percentage is calculated as wins divided by games played.

\[ Winning\ Percentage = \frac{W}{G} \]

baseball$Winning_Percentage <- baseball$W / baseball$G

head(baseball[, c("Team", "Year", "W", "G", "Winning_Percentage")])
##   Team Year  W   G Winning_Percentage
## 1  ARI 2012 81 162          0.5000000
## 2  ATL 2012 94 162          0.5802469
## 3  BAL 2012 93 162          0.5740741
## 4  BOS 2012 69 162          0.4259259
## 5  CHC 2012 61 162          0.3765432
## 6  CHW 2012 85 162          0.5246914

5. Summary Statistics for Key Baseball Variables

summary(baseball[, c("RS", "RA", "Run_Differential", "W", "OBP", "SLG", "BA")])
##        RS               RA         Run_Differential       W        
##  Min.   : 463.0   Min.   : 472.0   Min.   :-337     Min.   : 40.0  
##  1st Qu.: 652.0   1st Qu.: 649.8   1st Qu.: -72     1st Qu.: 73.0  
##  Median : 711.0   Median : 709.0   Median :   4     Median : 81.0  
##  Mean   : 715.1   Mean   : 715.1   Mean   :   0     Mean   : 80.9  
##  3rd Qu.: 775.0   3rd Qu.: 774.2   3rd Qu.:  74     3rd Qu.: 89.0  
##  Max.   :1009.0   Max.   :1103.0   Max.   : 309     Max.   :116.0  
##       OBP              SLG               BA        
##  Min.   :0.2770   Min.   :0.3010   Min.   :0.2140  
##  1st Qu.:0.3170   1st Qu.:0.3750   1st Qu.:0.2510  
##  Median :0.3260   Median :0.3960   Median :0.2600  
##  Mean   :0.3263   Mean   :0.3973   Mean   :0.2593  
##  3rd Qu.:0.3370   3rd Qu.:0.4210   3rd Qu.:0.2680  
##  Max.   :0.3730   Max.   :0.4910   Max.   :0.2940

6. Scatter Plot: Runs Scored vs. Wins

plot(
  baseball$RS,
  baseball$W,
  main = "Runs Scored vs. Wins",
  xlab = "Runs Scored",
  ylab = "Wins",
  pch = 19
)

7. Scatter Plot: Runs Allowed vs. Wins

plot(
  baseball$RA,
  baseball$W,
  main = "Runs Allowed vs. Wins",
  xlab = "Runs Allowed",
  ylab = "Wins",
  pch = 19
)

8. Scatter Plot: Run Differential vs. Wins

plot(
  baseball$Run_Differential,
  baseball$W,
  main = "Run Differential vs. Wins",
  xlab = "Run Differential",
  ylab = "Wins",
  pch = 19
)

abline(lm(W ~ Run_Differential, data = baseball), lwd = 2)

9. Build a Linear Regression Model

The model predicts wins using run differential.

\[ Wins = Intercept + Slope \times Run\ Differential \]

wins_model <- lm(W ~ Run_Differential, data = baseball)

summary(wins_model)
## 
## Call:
## lm(formula = W ~ Run_Differential, data = baseball)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -14.3767  -2.7765   0.0571   2.8022  12.8235 
## 
## Coefficients:
##                   Estimate Std. Error t value Pr(>|t|)    
## (Intercept)      80.904221   0.113335  713.85   <2e-16 ***
## Run_Differential  0.104548   0.001103   94.78   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 3.978 on 1230 degrees of freedom
## Multiple R-squared:  0.8796, Adjusted R-squared:  0.8795 
## F-statistic:  8983 on 1 and 1230 DF,  p-value: < 2.2e-16

10. Extract the Regression Equation

intercept <- coef(wins_model)[1]
slope <- coef(wins_model)[2]

intercept
## (Intercept) 
##    80.90422
slope
## Run_Differential 
##        0.1045482

The regression equation from this dataset is:

paste0(
  "Predicted Wins = ",
  round(intercept, 4),
  " + ",
  round(slope, 4),
  " * Run Differential"
)
## [1] "Predicted Wins = 80.9042 + 0.1045 * Run Differential"

11. Predict Wins for a Team with 763 Runs Scored and 614 Runs Allowed

First calculate run differential:

\[ 763 - 614 = 149 \]

Then plug the value into the regression model.

runs_scored <- 763
runs_allowed <- 614

new_run_differential <- runs_scored - runs_allowed
new_run_differential
## [1] 149
predicted_wins <- intercept + slope * new_run_differential
predicted_wins
## (Intercept) 
##    96.48191
round(predicted_wins, 1)
## (Intercept) 
##        96.5
round(predicted_wins, 0)
## (Intercept) 
##          96

A team that scores 763 runs and allows 614 runs is expected to win approximately 96.5 games, which rounds to about 96 wins.

12. Predict Using the predict() Function

new_team <- data.frame(Run_Differential = 149)

predict(wins_model, newdata = new_team)
##        1 
## 96.48191

13. Compare Playoff and Non-Playoff Teams

aggregate(W ~ Playoffs, data = baseball, FUN = mean)
##   Playoffs        W
## 1        0 77.39372
## 2        1 95.11885
aggregate(Run_Differential ~ Playoffs, data = baseball, FUN = mean)
##   Playoffs Run_Differential
## 1        0        -29.67004
## 2        1        120.13934

14. Boxplot: Wins by Playoff Status

boxplot(
  W ~ Playoffs,
  data = baseball,
  main = "Wins by Playoff Status",
  xlab = "Playoff Status",
  ylab = "Wins"
)

15. Top Teams by Wins

baseball_ordered <- baseball[order(-baseball$W), ]

head(baseball_ordered[, c("Team", "League", "Year", "RS", "RA", "Run_Differential", "W")], 10)
##      Team League Year  RS  RA Run_Differential   W
## 355   SEA     AL 2001 927 627              300 116
## 440   NYY     AL 1998 965 656              309 114
## 1070  BAL     AL 1969 779 517              262 109
## 706   NYM     NL 1986 783 578              205 108
## 955   CIN     NL 1975 840 586              254 108
## 1046  BAL     AL 1970 792 574              218 108
## 423   ATL     NL 1998 826 581              245 106
## 267   STL     NL 2004 855 659              196 105
## 507   ATL     NL 1993 767 559              208 104
## 656   OAK     AL 1988 800 620              180 104

Conclusion

This activity showed how to import and explore a baseball dataset in R, create run differential and winning percentage variables, visualize relationships between performance measures, build a linear regression model, and predict expected wins for a team based on runs scored and runs allowed.