2025-09-17

Introduction

  • Simple Linear Regression models the relationship between one predictor and one outcome.
  • Example: How car weight affects miles per gallon (mpg).
  • Useful for prediction and understanding associations.

The Linear Regression Model

We assume a linear form: \[ y_i = \beta_0 + \beta_1 x_i + \varepsilon_i, \quad \varepsilon_i \sim \mathcal{N}(0,\sigma^2) \]

  • \(\beta_0\): intercept (baseline)
  • \(\beta_1\): slope (effect of \(x\) on \(y\))
  • \(\varepsilon_i\): random error

Data Preview

data(mtcars)
mtcars |> select(mpg, wt, hp) |> slice_head(n = 6)
##                    mpg    wt  hp
## Mazda RX4         21.0 2.620 110
## Mazda RX4 Wag     21.0 2.875 110
## Datsun 710        22.8 2.320  93
## Hornet 4 Drive    21.4 3.215 110
## Hornet Sportabout 18.7 3.440 175
## Valiant           18.1 3.460 105

Scatter + Fitted Line (ggplot)

ggplot(mtcars, aes(x = wt, y = mpg)) +
  geom_point() +
  geom_smooth(method = "lm", se = TRUE) +
  labs(title = "MPG vs Weight", x = "Weight (1000 lbs)", y = "Miles per gallon")

Fit the Model (R code)

fit <- lm(mpg ~ wt, data = mtcars)
broom::tidy(fit)
## # A tibble: 2 × 5
##   term        estimate std.error statistic  p.value
##   <chr>          <dbl>     <dbl>     <dbl>    <dbl>
## 1 (Intercept)    37.3      1.88      19.9  8.24e-19
## 2 wt             -5.34     0.559     -9.56 1.29e-10

Interpretation of Results

  • Slope (\(\hat\beta_1\)): expected change in mpg for each +1000 lbs in weight.
  • Intercept (\(\hat\beta_0\)): predicted mpg when weight = 0 (not realistic but needed for the model).
  • P-value: tests whether slope is significantly different from 0.

Model Assumptions (LaTeX)

We assume: \[ \varepsilon_i \stackrel{iid}{\sim} \mathcal{N}(0,\sigma^2), \quad \mathbb{E}[\varepsilon_i]=0, \quad \operatorname{Var}(\varepsilon_i)=\sigma^2, \quad \text{Independence}. \]

Linearity: \(\mathbb{E}[Y\mid X]=\beta_0+\beta_1 X\).

Inference for the Slope (LaTeX + code)

Hypotheses: \(H_0:\beta_1=0\) vs \(H_a:\beta_1\neq 0\).
95% CI: \(\hat\beta_1 \pm t_{0.975,n-2}\,\mathrm{SE}(\hat\beta_1)\).

broom::glance(fit) |> dplyr::select(r.squared, adj.r.squared, sigma, p.value)
## # A tibble: 1 × 4
##   r.squared adj.r.squared sigma  p.value
##       <dbl>         <dbl> <dbl>    <dbl>
## 1     0.753         0.745  3.05 1.29e-10
confint(fit)
##                 2.5 %    97.5 %
## (Intercept) 33.450500 41.119753
## wt          -6.486308 -4.202635

Residuals vs Fitted (ggplot)

aug <- broom::augment(fit)
ggplot(aug, aes(.fitted, .resid)) +
  geom_hline(yintercept = 0, linetype = 2) +
  geom_point() +
  labs(x = "Fitted values", y = "Residuals", title = "Residuals vs Fitted")

Normal Q–Q Plot of Residuals (ggplot)

ggplot(aug, aes(sample = .resid)) +
  stat_qq() + stat_qq_line() +
  labs(title = "Normal Q–Q Plot of Residuals",
       x = "Theoretical Quantiles", y = "Sample Quantiles")

Predictions with Intervals (code)

new_cars <- tibble(wt = c(2.2, 3.0, 3.8))
pred_pi <- predict(fit, newdata = new_cars, interval = "prediction")
pred_ci <- predict(fit, newdata = new_cars, interval = "confidence")
cbind(new_cars, pred_pi)
##    wt      fit      lwr      upr
## 1 2.2 25.52729 19.10442 31.95016
## 2 3.0 21.25171 14.92987 27.57355
## 3 3.8 16.97613 10.62422 23.32805
cbind(new_cars, pred_ci)
##    wt      fit      lwr      upr
## 1 2.2 25.52729 23.92780 27.12678
## 2 3.0 21.25171 20.12444 22.37899
## 3 3.8 16.97613 15.69084 18.26143

3D Plot (plotly)

plot_ly(mtcars, x = ~wt, y = ~hp, z = ~mpg,
        type = "scatter3d", mode = "markers") |>
  layout(scene = list(
    xaxis = list(title = "Weight (1000 lbs)"),
    yaxis = list(title = "Horsepower"),
    zaxis = list(title = "MPG")
  ))

Takeaways

  • Strong negative relationship between weight and mpg.
  • Slope is statistically significant.
  • Assumptions appear reasonably satisfied.
  • Use intervals to make predictions responsibly.