

Linear Regression III
Grayson White
Stat 243
Week 3 | Fall 2026
Today:
Next time:
Goal: Use statistics calculated from data to make estimates about unknown parameters
Parameters: \(\beta_0\), \(\beta_1\)
Statistics: \(\hat{\beta}_0\), \(\hat{\beta}_1\)
Tools: confidence intervals, hypothesis tests
The Problems: Our model will change if built using a different random sample. So in addition to estimates, we need to know about variability
\[ \hat{\theta} \pm t^*_C \cdot \widehat{\mathrm{SE}}(\hat{\theta}) \]
In order to use simple linear regression for inference, we require the LINE assumptions.
Linearity: The relationship between explanatory and response variables must be approximately linear
Independence: The observations should be independent of one another.
Normality: The distribution of residuals should be approximately bell-shaped, unimodal, symmetric, and centered at 0 at every “slice” of the explanatory variable
Equal Variability: Variance of residuals should be roughly constant across data set. Also called “homoscedasticity”. Models that violate this assumption are sometimes called “heteroscedastic”
If one or more of these conditions do not hold, our predictions may not be accurate and we should be skeptical of inferential claims.
Assume the following true model: \[ f(x) = 12 + 0.7 x; \quad \epsilon \sim N(0, 4) \]
set.seed(145)
n <- 60
beta_0 <- 12
beta_1 <- .7
sigma <- 2
x <- rnorm(n, mean = 20, sd = 3)
f_mean <- beta_0 + beta_1*x
y <- f_mean + rnorm(n, mean = 0, sd = sigma)
my_data <- data.frame(x,y)
ggplot(my_data,
aes(x = x, y = y)) +
geom_abline(slope = beta_1,
intercept = 12) +
geom_point(color = "steelblue") +
geom_abline(slope = beta_1,
intercept = 12,
color = "goldenrod",
size = 1) +
theme_bw() +
annotate("text", x = 26, y = 29, label = "f(x)", color = "goldenrod",parse = T) +
labs(title = "Simulated Data from true model")
Assume the following true model: \[ f(x) = 12 + 0.7 x; \quad \epsilon \sim N(0, 4) \]
ggplot(my_data,
aes(x = x, y = y)) +
geom_abline(slope = beta_1,
intercept = 12,
color = "goldenrod",
size = 1) +
geom_point(color = "steelblue")+
geom_smooth(method = "lm",
se = F,
color = "black") +
theme_bw() +
annotate("text", x = 26, y = 29, label = "f(x)", color = "goldenrod", parse = T) +
annotate("text", x = 26, y = 32.5, label = "hat(f)(x)", color = "black", parse = T) +
labs(title = "Estimate for f based on 1 simulation")
Assume the following true model: \[ f(x) = 12 + 0.7 x; \quad \epsilon \sim N(0, 4) \]
set.seed(1020)
it <- 1000
slope <- rep(NA, times = it)
intercept <- rep(NA, times = it)
for(i in 1:it) {
x <- rnorm(n, mean = 20, sd = 3)
f_mean <- beta_0 + beta_1 * x
y <- f_mean + rnorm(n, mean = 0, sd = sigma)
slope[i] <- lm(y ~ x)$coef[[2]]
intercept[i] <- lm(y ~ x)$coef[[1]]
}
many_mods <- data.frame(slope, intercept)
ggplot(my_data,
aes(x = x, y = y)) +
geom_point(color = "steelblue") +
geom_abline(data = many_mods,
slope = slope,
intercept = intercept,
alpha = .02) +
geom_smooth(method = "lm",
se = F,
color = "black") +
geom_abline(slope = beta_1,
intercept = 12,
color = "goldenrod",
size = 1) +
theme_bw() +
labs(title = "Estimates for f based on 1000 simulations")



The Sampling Distribution has the following characteristics:
Centered at \(\beta_1\), i.e. \(\mathbb{E}(\hat{\beta}_1) = \beta_1\).
\(\mbox{Var}(\hat{\beta}_1) = \frac{\sigma^2}{S_{XX}}\).
\(\hat{\beta}_1 | X \sim N (\beta_1, \frac{\sigma^2}{S_{XX}})\).
Who cares?
We’d like to use the sampling distribution to build a CI for \(\beta\):
\[ \hat{\beta} \pm t^*_C \cdot \widehat{\mathrm{SE}}(\hat{\beta}) \]
Our best estimate of \(\beta_1\) is \(\hat{\beta}_1\) (since the expected value \(\hat \beta_1\) is \(\beta_1\))
However, we need to estimate \(\mbox{SE}(\hat\beta)\). How to do this?
Use the sampling distribution!! (Why can’t we?)
In reality we never have access to the true sampling distribution. Instead we approximate it by:
Distributional assumptions
\[\widehat{\mbox{SE}}(\hat{\beta}_1) = \frac{\hat \sigma}{\sqrt{\sum_{i=1}^n(x_i - \bar x)^2}}\]
Simulation (bootstrap)
Use the percentile or standard error method to estimate \(\mbox{SE}(\hat\beta_1)\) from estimates of \(\beta_1\) from many bootstrap samples.
Suppose we are interested in testing the claim that the slope is zero.
\[ H_0: \beta_1 = 0 \qquad \textrm{vs} \quad H_A: \beta_1 \ne 0 \]
Distributional assumptions
Consider the statistic \(t\) given by \[ t = \frac{\hat{\beta}_1}{\widehat{\mbox{SE}}(\hat{\beta}_1)} \]
\(t \sim t(\mbox{df} = n-2)\) and \(SE(\hat{\beta}_1)\) calculated the same as in the CI.
For linear regression, reasonable if we (1) meet the LINE conditions, and (2) have a sample size >30.
Simulation (permutation)
Use the percentile or standard error method to estimate \(\mbox{SE}(\hat\beta_1)\) from estimates of \(\beta_1\) from many permutations of your original dataset.
Response variable \((y)\): quantitative
Have 1 categorical explanatory variable \((x)\) with two categories.
Model form:
\[ \begin{align} y &= \beta_o + \beta_1 x + \epsilon \end{align} \]
Rows: 85
Columns: 13
$ competitorname <chr> "100 Grand", "3 Musketeers", "One dime", "One quarter…
$ chocolate <dbl> 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,…
$ fruity <dbl> 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1,…
$ caramel <dbl> 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,…
$ peanutyalmondy <dbl> 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,…
$ nougat <dbl> 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,…
$ crispedricewafer <dbl> 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,…
$ hard <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1,…
$ bar <dbl> 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,…
$ pluribus <dbl> 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1,…
$ sugarpercent <dbl> 0.732, 0.604, 0.011, 0.011, 0.906, 0.465, 0.604, 0.31…
$ pricepercent <dbl> 0.860, 0.511, 0.116, 0.511, 0.511, 0.767, 0.767, 0.51…
$ winpercent <dbl> 66.97173, 67.60294, 32.26109, 46.11650, 52.34146, 50.…
What might be a good categorical explanatory variable of winpercent?
Before building the model, let’s explore and visualize the data!
What dplyr functions should I use to find the mean and sd of winpercent by the categories of chocolate?
What graph should we use to visualize the winpercent scores by chocolate?
ggplot(candy, aes(x = factor(chocolate),
y = winpercent,
fill = factor(chocolate))) +
geom_boxplot() +
stat_summary(fun = mean,
geom = "point",
color = "yellow",
size = 4) +
guides(fill = "none") +
scale_fill_manual(values =
c("0" = "deeppink",
"1" = "chocolate4")) +
scale_x_discrete(labels = c("No", "Yes"),
name =
"Does the candy contain chocolate?")
Model Form:
\[ \begin{align} y &= \beta_o + \beta_1 x + \epsilon \end{align} \]
When \(x = 0\): \(\qquad y = \beta_o + \epsilon\)
When \(x = 1\): \(\qquad y = \beta_o + \beta_1 + \epsilon\)
When the explanatory variable is categorical, \(\beta_o\) and \(\beta_1\) no longer represent the intercept and slope.
Now \(\beta_o\) represents the (population) mean of the response variable when \(x = 0\).
And, \(\beta_1\) represents the change in the (population) mean response going from \(x = 0\) to \(x = 1\).
Can also do prediction:

Rows: 344
Columns: 8
$ species <fct> Adelie, Adelie, Adelie, Adelie, Adelie, Adelie, Adel…
$ island <fct> Torgersen, Torgersen, Torgersen, Torgersen, Torgerse…
$ bill_length_mm <dbl> 39.1, 39.5, 40.3, NA, 36.7, 39.3, 38.9, 39.2, 34.1, …
$ bill_depth_mm <dbl> 18.7, 17.4, 18.0, NA, 19.3, 20.6, 17.8, 19.6, 18.1, …
$ flipper_length_mm <int> 181, 186, 195, NA, 193, 190, 181, 195, 193, 190, 186…
$ body_mass_g <int> 3750, 3800, 3250, NA, 3450, 3650, 3625, 4675, 3475, …
$ sex <fct> male, female, female, NA, female, male, female, male…
$ year <int> 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007…
We’d like to predict a penguin’s bill length based on their species.
Response variable?
Explanatory variable?
How do we handle more than 2 groups???
\[ y = \beta_o + \beta_1 x_{species:Chinstrap} + \beta_2 x_{species:Gentoo} + \epsilon \]
# A tibble: 3 × 7
term estimate std_error statistic p_value lower_ci upper_ci
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 intercept 38.8 0.241 161. 0 38.3 39.3
2 species: Chinstrap 10.0 0.432 23.2 0 9.19 10.9
3 species: Gentoo 8.71 0.36 24.2 0 8.01 9.42
\[\begin{align*} \hat{y} &= \hat{\beta}_o + \hat{\beta}_1 \cdot x_{species:Chinstrap} + \hat{\beta}_2 \cdot x_{species:Gentoo} \\ &= 38.8 + 10.0 \cdot x_{species:Chinstrap} + 8.71 \cdot x_{species:Gentoo} \end{align*}\]
Coefficient interpretation?
We predicted a penguin’s bill length based on their species.
We’ll incorporate bill depth for prediction!

ggplot(penguins, aes(x = bill_depth_mm, y = bill_length_mm, color = species)) +
geom_point(size = 2) +
geom_smooth(inherit.aes = FALSE,
mapping = aes(x = bill_depth_mm,
y = bill_length_mm),
method = "lm",
se = FALSE,
color = "red") +
geom_parallel_slopes(se = FALSE) +
scale_color_manual(values = c("steelblue",
"goldenrod",
"plum3")) +
theme_bw() +
theme(legend.position = "bottom")
# A tibble: 3 × 2
term estimate
<chr> <dbl>
1 intercept 38.8
2 species: Chinstrap 10.0
3 species: Gentoo 8.71
# A tibble: 4 × 7
term estimate std_error statistic p_value lower_ci upper_ci
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 intercept 13.2 2.25 5.88 0 8.80 17.6
2 bill_depth_mm 1.39 0.122 11.4 0 1.15 1.63
3 species: Chinstrap 9.94 0.368 27.0 0 9.22 10.7
4 species: Gentoo 13.4 0.512 26.2 0 12.4 14.4
\[ \hat{y}= 13.2 + 1.39 \cdot x_{\textrm{Bill Depth}} + 9.94 \cdot x_{\textrm{Species:Chinstrap}} + 13.4 \cdot x_{\textrm{Species:Gentoo}} \]
# A tibble: 4 × 7
term estimate std_error statistic p_value lower_ci upper_ci
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 intercept 13.2 2.25 5.88 0 8.80 17.6
2 bill_depth_mm 1.39 0.122 11.4 0 1.15 1.63
3 species: Chinstrap 9.94 0.368 27.0 0 9.22 10.7
4 species: Gentoo 13.4 0.512 26.2 0 12.4 14.4
\[ \hat{y}= 13.2 + 1.39 \cdot x_{\textrm{Bill Depth}} + 9.94 \cdot x_{\textrm{Species:Chinstrap}} + 13.4 \cdot x_{\textrm{Species:Gentoo}} \]

Are equal slopes a reasonable assumption here?

Equal slopes models force the relationship between quantitative predictors and the response variable to be the same for each group in the model.
In contrast, different slopes models allow for different relationships between quantitative predictors and the response variable for each group in the model.
How can we allow our model to have different slopes?
Recall the equal slopes model:
\[ y = \beta_o + \beta_1 \cdot x_{\textrm{Bill Depth}} + \beta_2 \cdot x_{\textrm{Species:Chinstrap}} + \beta_3 \cdot x_{\textrm{Species:Gentoo}} + \epsilon \]
How can we allow the slopes to vary?
\[ y = \beta_o + \beta_1 \cdot x_{\textrm{Bill Depth}} + \beta_2 \cdot x_{\textrm{Species:Chinstrap}} + \beta_3 \cdot x_{\textrm{Species:Gentoo}} + \\ \beta_4 \cdot x_{\textrm{Bill Depth}} \cdot x_{\textrm{Species:Chinstrap}} + \beta_5 \cdot x_{\textrm{Bill Depth}} \cdot x_{\textrm{Species:Gentoo}} + \epsilon \]
# A tibble: 4 × 7
term estimate std_error statistic p_value lower_ci upper_ci
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 intercept 13.2 2.25 5.88 0 8.80 17.6
2 bill_depth_mm 1.39 0.122 11.4 0 1.15 1.63
3 species: Chinstrap 9.94 0.368 27.0 0 9.22 10.7
4 species: Gentoo 13.4 0.512 26.2 0 12.4 14.4
# A tibble: 6 × 7
term estimate std_error statistic p_value lower_ci upper_ci
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 intercept 23.1 3.02 7.65 0 17.1 29.0
2 bill_depth_mm 0.857 0.164 5.22 0 0.534 1.18
3 species: Chinstrap -9.64 5.72 -1.69 0.093 -20.9 1.60
4 species: Gentoo -5.84 4.54 -1.29 0.199 -14.8 3.08
5 bill_depth_mm:speciesC… 1.06 0.31 3.44 0.001 0.455 1.68
6 bill_depth_mm:speciesG… 1.16 0.279 4.17 0 0.615 1.71