Executive Summary

Using the mtcars data (32 cars, 1973-74 models), I examined whether automatic or manual transmissions are better for miles per gallon (MPG) and by how much.

Exploratory Data Analysis

str(mtcars[, c("mpg", "am", "wt", "qsec", "hp", "cyl")])
## 'data.frame':    32 obs. of  6 variables:
##  $ mpg : num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
##  $ am  : Factor w/ 2 levels "Automatic","Manual": 2 2 2 1 1 1 1 1 1 1 ...
##  $ wt  : num  2.62 2.88 2.32 3.21 3.44 ...
##  $ qsec: num  16.5 17 18.6 19.4 17 ...
##  $ hp  : num  110 110 93 110 175 105 245 62 95 123 ...
##  $ cyl : num  6 6 4 6 8 6 8 4 4 6 ...
aggregate(mpg ~ am, data = mtcars, function(x) c(n = length(x), mean = mean(x), sd = sd(x)))
##          am     mpg.n  mpg.mean    mpg.sd
## 1 Automatic 19.000000 17.147368  3.833966
## 2    Manual 13.000000 24.392308  6.166504
aggregate(wt ~ am, data = mtcars, mean)
##          am       wt
## 1 Automatic 3.768895
## 2    Manual 2.411000

Manual cars have higher MPG (boxplot, Appendix Fig. 1), but they are also much lighter on average (about 2.4 vs 3.8 thousand lbs), so weight confounds the comparison. Appendix Fig. 2 shows pairwise relationships: wt, cyl, disp, and hp are strongly negatively correlated with MPG.

Model Selection Strategy

  1. Simple model mpg ~ am answers the raw question but ignores confounders.
  2. Full model with all predictors is over-parameterized for n = 32 and has collinear predictors (large VIFs), so few terms are significant.
  3. Stepwise selection (AIC, step() in both directions) from the full model picks the candidate below.
  4. Nested-model F-tests check whether each added variable is justified.
formula(fit_step)
## mpg ~ wt + qsec + am
anova(fit_simple, fit_wt, fit_final)
## Analysis of Variance Table
## 
## Model 1: mpg ~ am
## Model 2: mpg ~ am + wt
## Model 3: mpg ~ wt + qsec + am
##   Res.Df    RSS Df Sum of Sq      F    Pr(>F)    
## 1     30 720.90                                  
## 2     29 278.32  1    442.58 73.203 2.673e-09 ***
## 3     28 169.29  1    109.03 18.034 0.0002162 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
data.frame(model = c("am only", "am + wt", "wt + qsec + am", "full"),
           adj_R2 = c(summary(fit_simple)$adj.r.squared,
                      summary(fit_wt)$adj.r.squared,
                      summary(fit_final)$adj.r.squared,
                      summary(fit_full)$adj.r.squared))
##            model    adj_R2
## 1        am only 0.3384589
## 2        am + wt 0.7357889
## 3 wt + qsec + am 0.8335561
## 4           full 0.8066423

The stepwise model mpg ~ wt + qsec + am is my final choice: adding wt and qsec significantly improves fit (F-tests), and it has the highest adjusted R^2 among the candidates. I also tested an am:wt interaction:

summary(fit_inter)$coefficients
##              Estimate Std. Error   t value     Pr(>|t|)
## (Intercept)  9.723053  5.8990407  1.648243 0.1108925394
## wt          -2.936531  0.6660253 -4.409038 0.0001488947
## qsec         1.016974  0.2520152  4.035366 0.0004030165
## amManual    14.079428  3.4352512  4.098515 0.0003408693
## wt:amManual -4.141376  1.1968119 -3.460340 0.0018085763
anova(fit_final, fit_inter)
## Analysis of Variance Table
## 
## Model 1: mpg ~ wt + qsec + am
## Model 2: mpg ~ wt + qsec + am + am:wt
##   Res.Df    RSS Df Sum of Sq      F   Pr(>F)   
## 1     28 169.29                                
## 2     27 117.28  1     52.01 11.974 0.001809 **
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

The interaction is significant, suggesting the transmission effect differs by weight (see Limitations); I keep the simpler additive model for the headline number and note this nuance.

Results and Interpretation of Coefficients

summary(fit_final)$coefficients
##              Estimate Std. Error   t value     Pr(>|t|)
## (Intercept)  9.617781  6.9595930  1.381946 1.779152e-01
## wt          -3.916504  0.7112016 -5.506882 6.952711e-06
## qsec         1.225886  0.2886696  4.246676 2.161737e-04
## amManual     2.935837  1.4109045  2.080819 4.671551e-02
confint(fit_final)
##                   2.5 %    97.5 %
## (Intercept) -4.63829946 23.873860
## wt          -5.37333423 -2.459673
## qsec         0.63457320  1.817199
## amManual     0.04573031  5.825944

Residual Diagnostics

par(mfrow = c(2, 2))
plot(fit_final)

par(mfrow = c(1, 1))
shapiro.test(resid(fit_final))                       # normality of residuals
## 
##  Shapiro-Wilk normality test
## 
## data:  resid(fit_final)
## W = 0.9411, p-value = 0.08043
head(sort(hatvalues(fit_final), decreasing = TRUE), 3)  # leverage
##            Merc 230 Lincoln Continental   Chrysler Imperial 
##           0.2970422           0.2642151           0.2296338
head(sort(abs(dfbetas(fit_final)[, "amManual"]), decreasing = TRUE), 3)  # influence on am
## Chrysler Imperial          Fiat 128        Volvo 142E 
##         0.5626418         0.4765680         0.4156482

Residuals vs. fitted show no strong pattern, the Q-Q plot is approximately straight, and the Shapiro-Wilk test does not reject normality. A few points (e.g., Chrysler Imperial, Fiat 128, Toyota Corona) have somewhat higher leverage or influence, but none are extreme (Cook’s distance is small).

Answering the Questions of Interest

Is automatic or manual better for MPG? In this sample, manual is associated with better MPG, but after adjusting for weight and acceleration the effect is smaller and only borderline significant.

How big is the difference? Unadjusted: about 7.2 MPG. Adjusted: about 2.9 MPG, with a 95% CI of 0 to 5.8 MPG. The interval is wide, so the true difference could be close to zero or fairly large.

Limitations. Only 32 cars from 1973-74; observational data (no random assignment of transmission), so causal claims are not justified; transmission is correlated with weight and engine design; the significant interaction means the effect likely varies with weight.

Appendix

Fig. 1: MPG by transmission

ggplot(mtcars, aes(am, mpg, fill = am)) + geom_boxplot(show.legend = FALSE) +
  labs(x = "Transmission", y = "Miles per gallon")

Fig. 2: Pairwise relationships

pairs(mtcars[, c("mpg", "wt", "qsec", "hp", "disp", "cyl")],
      panel = panel.smooth, col = ifelse(mtcars$am == "Manual", "blue", "red"))

Fig. 3: MPG vs. weight by transmission

ggplot(mtcars, aes(wt, mpg, color = am)) + geom_point() +
  geom_smooth(method = "lm", se = FALSE) +
  labs(x = "Weight (1000 lbs)", y = "MPG", color = "Transmission")

Full-model variance inflation (collinearity check)

car::vif(fit_full)
##       cyl      disp        hp      drat        wt      qsec        vs        am 
## 15.373833 21.620241  9.832037  3.374620 15.164887  7.527958  4.965873  4.648487 
##      gear      carb 
##  5.357452  7.908747