My question

How much can I learn about a car’s fuel efficiency just from its weight?

I picked this because predicting a number from a few features is a common data science task. Linear regression seems like a reasonable first model.

My guess: heavier cars will usually have lower miles per gallon (MPG).

I’ll also check whether horsepower adds useful information.

The data

I used mtcars, a dataset included with R.

  • 32 cars from the 1973-74 model years, reported in Motor Trend in 1974.
  • Response: mpg, measured in miles per US gallon.
  • Main predictor: wt, measured in thousands of pounds.
  • Extra variables: horsepower (hp) and number of cylinders (cyl).

There are no missing values in these variables. This is a small historical sample, so I wouldn’t use it to estimate a modern car’s MPG.

Heavier cars tend to get lower MPG

The downward pattern supports my guess. Pearson’s correlation is -0.87. The shaded band is a 95% confidence interval for the mean MPG.

The regression idea

The model relates each car’s weight to its MPG:

\[ Y_i = \beta_0 + \beta_1 x_i + \varepsilon_i \]

Here, \(x_i\) is weight in 1,000 lb and \(Y_i\) is MPG. The slope \(\beta_1\) describes the change in mean MPG for one extra unit of weight.

Least squares chooses the coefficients that minimize squared residuals:

\[ \operatorname{SSE} = \sum_{i=1}^{n}\left[y_i-(\hat\beta_0+\hat\beta_1x_i)\right]^2 \]

A residual is the actual MPG minus the model’s predicted MPG.

The R code behind the model

library(ggplot2)
library(plotly)
cars <- datasets::mtcars
fit <- lm(mpg ~ wt, data = cars)
summary(fit)
confint(fit)
predict(fit, data.frame(wt = 3),
        interval = "prediction")

lm() fits the line. confint() gives intervals for its coefficients, and predict() estimates MPG for a 3,000 lb car.

What the fitted line says

\[ \widehat{\text{MPG}} = 37.29 - 5.34\times\text{Weight (1,000 lb)} \]

  • In this sample, an additional 1,000 lb is associated with about 5.34 fewer MPG on average.
  • The slope’s 95% confidence interval is [-6.49, -4.20] MPG per 1,000 lb.
  • \(R^2 = 0.753\): weight explains about 75% of the observed variation in MPG in this sample.

The intercept describes a zero-weight car, which falls outside the data and has no useful physical interpretation here.

One prediction still has uncertainty

For a 3,000 lb car, the fitted MPG is:

\[ \hat y(3) = 37.29 - 5.34(3) \approx 21.3\text{ MPG} \]

Quantity Range
95% CI for mean MPG at 3,000 lb 20.1 to 22.4 MPG
95% prediction interval for one car 14.9 to 27.6 MPG

The prediction interval is wider because individual cars vary around the mean. Both intervals depend on the regression assumptions.

Where the line misses

Several cars have large errors, and the positive residuals near both ends suggest some curvature. I’d check a nonlinear model next. This plot alone cannot establish normal errors or independence.

Does the model predict cars it did not fit?

I used leave-one-out cross-validation: fit on 31 cars, predict the omitted car, and repeat for all 32 cars.

\[ \operatorname{RMSE}_{\text{LOO}} = \sqrt{\frac{1}{32}\sum_{i=1}^{32}(y_i-\hat y_{(-i)})^2} \]

Lower is better. Adding horsepower reduces RMSE from 3.20 to 2.78 MPG.

Exploring the cars in 3D

Drag to rotate and hover to identify a car. Heavier cars often also have more horsepower, so the predictors overlap. This view shows associations, not separate causal effects.

What I would be careful about

  • Association and causation: other features differ across cars. This analysis cannot isolate the effect of changing weight.
  • Model assumptions: the intervals assume a linear mean, independent errors with constant variance, and normal errors for exact inference.
  • Limited data: 32 older cars do not represent today’s vehicle market. Cross-validation reuses this same narrow sample.
  • Extrapolation: observed weights run from 1.513 to 5.424 thousand lb. Predictions far outside that range would be hard to defend.

What I learned

Weight gives a useful first estimate of MPG in this dataset. The fitted slope is about -5.34 MPG per additional 1,000 lb.

But a strong relationship does not make every prediction accurate. The prediction interval and residual plot make that clear.

Adding horsepower improves the cross-validation result, although I would want newer and more varied data before using the model in practice.

My main takeaway: a regression line is a starting point. Checking its errors and predictions is part of the analysis.

Sources and reproducibility

  • Dataset: R Core Team, datasets::mtcars, Motor Trend Car Road Tests. Original source: Henderson and Velleman (1981), Biometrics, 37(2), 391-411.
  • Methods: R’s built-in stats functions lm(), confint() and predict.lm().
  • Figures: I used ggplot2 for the static plots and plotly for the interactive plot. All numerical results come from the R code in this file.

The Rmd uses built-in data and has no external data or image files. Required packages: rmarkdown, ggplot2, and plotly. Use the arrow keys to move between slides.