STAT 204 – Introduction to Statistical Data Analysis
19 Oct 2025
By the end of today’s class, you will be able to:
lm() in RToday we’ll work with the famous Palmer Penguins dataset!
Research Question:
Can we describe penguin body mass using other measurements?
Simple Linear Regression: \[Y_i = \beta_0 + \beta_1 X_i + \epsilon_i\]
where:
Multiple Linear Regression: \[Y_i = \beta_0 + \beta_1 X_{i1} + \beta_2 X_{i2} + \cdots + \beta_p X_{ip} + \epsilon_i\]
Or in matrix notation: \[\mathbf{Y} = \mathbf{X}\boldsymbol{\beta} + \boldsymbol{\epsilon}\]
where \(\mathbf{X}\) is the design matrix and \(\boldsymbol{\beta}\) is the coefficient vector.
Before we dive into estimation, what do we assume?
We write this as: \(\epsilon_i \overset{iid}{\sim} N(0, \sigma^2)\)
library(palmerpenguins)
data(penguins)
# Your turn:
# 1. What variables are available?
# 2. Which could be predictors?
# 3. Create a scatter plot of body_mass_g vs flipper_length_mm
# 4. Which other variables would you try as predictors?
ggplot(penguins, aes(x = flipper_length_mm, y = body_mass_g)) +
geom_point() +
geom_smooth(method = "lm", se = FALSE)Discussion: What relationships do you see?
We want to find \(\hat{\beta}_0\) and \(\hat{\beta}_1\) that minimize the Sum of Squared Residuals (SSR):
\[\text{SSR} = \sum_{i=1}^{n} (Y_i - \hat{Y}_i)^2 = \sum_{i=1}^{n} (Y_i - \hat{\beta}_0 - \hat{\beta}_1 X_i)^2\]
This is called the Ordinary Least Squares (OLS) criterion.
Take partial derivatives and set to zero:
\[\frac{\partial \text{SSR}}{\partial \beta_0} = -2\sum_{i=1}^{n}(Y_i - \hat{\beta}_0 - \hat{\beta}_1 X_i) = 0\]
\[\frac{\partial \text{SSR}}{\partial \beta_1} = -2\sum_{i=1}^{n}X_i(Y_i - \hat{\beta}_0 - \hat{\beta}_1 X_i) = 0\]
These are the normal equations.
Solving the normal equations gives:
\[\hat{\beta}_1 = \frac{\sum_{i=1}^{n}(X_i - \bar{X})(Y_i - \bar{Y})}{\sum_{i=1}^{n}(X_i - \bar{X})^2} = \frac{S_{XY}}{S_{XX}}\]
\[\hat{\beta}_0 = \bar{Y} - \hat{\beta}_1\bar{X}\]
Key insight: The regression line always passes through \((\bar{X}, \bar{Y})\)!
In multiple regression, the OLS estimator is:
\[\hat{\boldsymbol{\beta}} = (\mathbf{X}^T\mathbf{X})^{-1}\mathbf{X}^T\mathbf{Y}\]
This elegant formula gives us all coefficient estimates at once!
Condition: \(\mathbf{X}^T\mathbf{X}\) must be invertible (no perfect multicollinearity).
The lm() function does all the matrix algebra for us!
# Fit a simple linear regression model using LA
# Extract the response variable (y)
y <- penguins$body_mass_g
# Create the design matrix (X)
# Include intercept (column of 1s) and predictor variable
X <- cbind(1, penguins$flipper_length_mm)
# Remove rows with missing values (to match what lm() does)
complete_cases <- complete.cases(y, X)
y <- y[complete_cases]
X <- X[complete_cases, ]
# Calculate coefficients using linear algebra: β = (X'X)^(-1)X'y
beta_hat <- ## complete the code
# Display the results
beta_hat
# Compare with lm() results
model1 <- lm(body_mass_g ~ flipper_length_mm, data = penguins)
coef(model1)
# Give names to our manually calculated coefficients
rownames(beta_hat) <- c("(Intercept)", "flipper_length_mm")
beta_hatThe intercept is the expected value of \(Y\) when \(X = 0\).
Example: If predicting body mass from flipper length: \[\hat{\text{Body Mass}} = -5780.83 + 49.69 \times \text{Flipper Length}\]
Important: This has no practical interpretation here (a penguin can’t have 0 mm flippers!).
The slope is the expected change in \(Y\) for a one-unit increase in \(X\).
Example: \[\hat{\text{Body Mass}} = -5780.83 + 49.69 \times \text{Flipper Length}\]
Units matter! Always interpret in context with units.
Each coefficient is interpreted as the expected change in \(Y\) for a one-unit change in that predictor, holding all other predictors constant.
Under the standard assumptions, OLS estimators are:
BLUE means: Among all linear unbiased estimators, OLS has the smallest variance!
For simple linear regression:
\[\text{Var}(\hat{\beta}_1) = \frac{\sigma^2}{\sum_{i=1}^{n}(X_i - \bar{X})^2} = \frac{\sigma^2}{S_{XX}}\]
\[\text{Var}(\hat{\beta}_0) = \sigma^2\left(\frac{1}{n} + \frac{\bar{X}^2}{S_{XX}}\right)\]
Key insight: More spread in \(X\) (larger \(S_{XX}\)) gives more precise estimates!
We estimate the error variance using the Mean Squared Error (MSE):
\[\hat{\sigma}^2 = \text{MSE} = \frac{\sum_{i=1}^{n}(Y_i - \hat{Y}_i)^2}{n - p - 1} = \frac{\text{SSR}}{n - p - 1}\]
where \(p\) is the number of predictors.
The denominator \((n - p - 1)\) gives us degrees of freedom.
R-squared (\(R^2\)) measures the proportion of variance in \(Y\) explained by the model:
\[R^2 = 1 - \frac{\text{SSR}}{\text{SST}} = 1 - \frac{\sum(Y_i - \hat{Y}_i)^2}{\sum(Y_i - \bar{Y})^2}\]
Problem: \(R^2\) always increases when we add predictors!
Solution: Adjusted R-squared penalizes model complexity:
\[R^2_{\text{adj}} = 1 - \frac{\text{SSR}/(n-p-1)}{\text{SST}/(n-1)} = 1 - \frac{n-1}{n-p-1}(1-R^2)\]
Use \(R^2_{\text{adj}}\) when comparing models with different numbers of predictors.
We test: \(H_0: \beta_j = 0\) vs. \(H_a: \beta_j \neq 0\)
Test statistic: \[t = \frac{\hat{\beta}_j}{\text{SE}(\hat{\beta}_j)} \sim t_{n-p-1}\]
p-value: Probability of observing a test statistic of this value or more extreme given that \(H_0\) is true.
Reference: Wasserstein, R. L., & Lazar, N. A. (2016). The ASA Statement on p-Values: Context, Process, and Purpose. The American Statistician, 70(2), 129-133.
ASA Principle #1
“P-values can indicate how incompatible the data are with a specified statistical model.”
A p-value tells us: The probability of obtaining results at least as extreme as observed, assuming the null hypothesis is true
A p-value does NOT tell us:
ASA Principles #2 & #3
P-values do not measure the probability that the studied hypothesis is true. Scientific conclusions should not be based solely on whether a p-value passes a specific threshold.
Problems with p < 0.05:
ASA Recommendations
Proper inference requires full reporting, transparency, and consideration of multiple factors beyond p-values.
Key practices:
Bottom line: Accept uncertainty, be thoughtful, be open, and be modest in your claims.
A \((1-\alpha)100\%\) confidence interval for \(\beta_j\):
\[\hat{\beta}_j \pm t_{\alpha/2, n-p-1} \times \text{SE}(\hat{\beta}_j)\]
Interpretation: We are \((1-\alpha)100\%\) confident that the true \(\beta_j\) lies in this interval.
# 95% confidence intervals for coefficients
confint(model2, level = 0.95)
# For predictions
new_penguin <- data.frame(flipper_length_mm = 200,
bill_length_mm = 45,
bill_depth_mm = 15)
predict(model2, newdata = new_penguin,
interval = "confidence")
predict(model2, newdata = new_penguin,
interval = "prediction")library(ggplot2)
# Add predictions to data
penguins_clean <- penguins %>%
drop_na(any_of(c("body_mass_g","bill_length_mm",
"bill_depth_mm")))%>%
mutate(fitted = fitted(model2),
residuals = residuals(model2))
# Plot actual vs fitted
ggplot(penguins_clean, aes(x = fitted, y = body_mass_g)) +
geom_point(alpha = 0.5) +
geom_abline(slope = 1, intercept = 0, color = "blue") +
labs(title = "Actual vs Fitted Values", x = "Fitted Body Mass (g)",y = "Actual Body Mass (g)")Tests: \(H_0\): All slope coefficients are zero (\(\beta_1 = \beta_2 = \cdots = \beta_p = 0\))
Test statistic: \[F = \frac{(\text{SST} - \text{SSR})/p}{\text{SSR}/(n-p-1)} = \frac{\text{MSR}}{\text{MSE}} \sim F_{p, n-p-1}\]
This appears at the bottom of summary() output.
When predictors are on different scales, standardized coefficients help compare importance:
Now coefficients represent change in \(Y\) for a 1 SD change in \(X\).
R automatically creates dummy variables for factors:
The reference category (Adelie) is absorbed into the intercept.
Test whether the effect of one predictor depends on another:
Key concepts covered:
lm()Next session: Model diagnostics and selection!
By the end of today’s class, you will be able to:
Remember our assumptions?
If assumptions are violated: Estimates may be biased, hypothesis tests invalid, predictions unreliable.
We use diagnostic plots and statistical tests to check these!
Residual for observation \(i\): \[e_i = Y_i - \hat{Y}_i\]
Standardized residual: \[r_i = \frac{e_i}{\hat{\sigma}\sqrt{1 - h_{ii}}}\]
where \(h_{ii}\) is the leverage (diagonal element of the hat matrix \(\mathbf{H} = \mathbf{X}(\mathbf{X}^T\mathbf{X})^{-1}\mathbf{X}^T\)).
Purpose: Check linearity and homoscedasticity
What to look for:
Purpose: Check normality of residuals
What to look for: Points should fall approximately on the diagonal line.
Patterns indicate:
Minor deviations: Usually okay, especially with large \(n\)
Purpose: Check homoscedasticity
This plots \(\sqrt{|\text{standardized residuals}|}\) vs fitted values.
What to look for: Horizontal line with equal spread → constant variance ✓
Purpose: Identify influential observations
Cook’s distance measures influence of each observation.
Rule of thumb: Cook’s distance > 1 indicates influential point.
Tests for heteroscedasticity.
\(H_0\): Homoscedasticity (constant variance)
If p-value is very small: Reject \(H_0\), evidence of heteroscedasticity.
Tests for normality of residuals.
\(H_0\): Residuals are normally distributed
Important: With large \(n\), this test is very sensitive. Visual inspection (Q-Q plot) often more useful.
Tests for autocorrelation in residuals (common in time series).
\(H_0\): No autocorrelation
Test statistic ≈ 2 suggests no autocorrelation.
Potential solutions:
We often have many potential predictors. Questions:
Goal: Find the model that predicts best on new data!
Underfitting (too simple):
Overfitting (too complex):
Goal: Find the sweet spot!
Algorithm:
Algorithm:
Combines forward and backward:
# Create a full model with all available predictors
full_model <- lm(body_mass_g ~ flipper_length_mm + bill_length_mm +
bill_depth_mm + species + sex + island,
data = penguins)
# Try different directions
step_forward <- step(lm(body_mass_g ~ 1, data = penguins),
scope = formula(full_model),
direction = "forward")
step_backward <- step(full_model, direction = "backward")
# Do they give the same final model?AIC balances model fit and complexity:
\[\text{AIC} = -2\log(L) + 2p\]
where \(L\) is the likelihood and \(p\) is the number of parameters.
For linear regression: \[\text{AIC} = n\log(\text{SSR}/n) + 2p\]
Lower AIC is better! AIC penalizes adding parameters.
BIC is similar to AIC but penalizes complexity more:
\[\text{BIC} = -2\log(L) + p\log(n)\]
For linear regression: \[\text{BIC} = n\log(\text{SSR}/n) + p\log(n)\]
Lower BIC is better! BIC tends to select simpler models than AIC.
# Fit several models
model1 <- lm(body_mass_g ~ flipper_length_mm, data = penguins)
model2 <- lm(body_mass_g ~ flipper_length_mm + bill_length_mm, data = penguins)
model3 <- lm(body_mass_g ~ flipper_length_mm + bill_length_mm + species,
data = penguins)
# Compare AIC
AIC(model1, model2, model3)
# Compare BIC
BIC(model1, model2, model3)Guideline: Difference in AIC > 2 suggests models are meaningfully different.
Idea: Estimate prediction error on unseen data.
K-Fold Cross-Validation:
Common: \(K = 5\) or \(K = 10\)
Special case: \(K = n\)
CV error: \[\text{CV} = \frac{1}{n}\sum_{i=1}^{n}(Y_i - \hat{Y}_{-i})^2\]
where \(\hat{Y}_{-i}\) is prediction for \(i\) using model trained without observation \(i\).
Computationally expensive but can use shortcut for linear regression!
\[\text{CV} = \frac{1}{n}\sum_{i=1}^{n}\left(\frac{e_i}{1 - h_{ii}}\right)^2\] where \(e_i\) is the residual and \(h_{ii}\) is the leverage.
This is called the PRESS statistic (Predicted Residual Sum of Squares).
Conduct a complete analysis:
📚 Recommended:
💻 R packages:
![]()
STAT 204 – Intro to Statistical Data Analysis