1 Scenario and Dataset

A voluntary exam-prep workshop for first-year students seems to help exam performance, but the programme coordinator wants to know whether that apparent benefit just stands in for how much a student studies and how well a student sleeps.

You have anonymized records for 150 first-year students: weekly study hours, a sleep-quality score, workshop attendance, and exam score. Build a regression model that answers this in stages, and check that it can be trusted before reporting it.

data/exam_performance_lab.csv contains 150 rows, one per student.

Variable Type Description
student_id Integer Anonymous student identifier, 1-150
study_hours Continuous Self-reported hours spent studying for this exam in the two weeks before it
sleep_quality Continuous Self-rated sleep quality over the same period, on a 1-10 scale (1 = very poor, 10 = excellent)
workshop Categorical (2 levels) Whether the student attended the exam-prep workshop: “Workshop” or “No Workshop”
exam_score Continuous Score on the standardized introductory exam, 0-100

This practical works through simple regression, multiple regression, dummy coding, and testing whether a continuous predictor’s effect differs across a categorical predictor’s levels (an interaction), using the LINE diagnostics from the lecture. Throughout, \(k\) denotes the number of predictors in a given model.

2 Questions

Work through the tasks below in order. Each part builds on the model from the part before it. Use data/exam_performance_lab.csv.

Part A – Getting to know the data

  1. Load the dataset and report the sample size, and the mean and standard deviation of study_hours, sleep_quality, and exam_score, separately for each workshop group.
  2. Produce a scatterplot of exam_score against study_hours, coloring or marking the points by workshop group. Describe, in a sentence or two, what the plot suggests about the relationship between study hours and exam score, and about whether that relationship looks similar in the two groups.
  3. Report the correlation between study_hours and sleep_quality. Why does this correlation matter for how you interpret the multiple regression models in Parts C and D?

Part B – Research question 1: does weekly study time predict exam performance?

  1. Fit a simple linear regression predicting exam_score from study_hours (Model 1). Report the intercept, the slope, and \(R^2\).
  2. State, in one sentence, what the slope means in terms of study hours and exam score. Include the correct units.
  3. Is the effect of study_hours statistically significant? Report the test statistic, the degrees of freedom, and the \(p\)-value, and state your conclusion.

Part C – Research question 2: does sleep quality explain exam performance beyond study time?

  1. Add sleep_quality to the model (Model 2). Report the new coefficients and \(R^2\).
  2. By how much did \(R^2\) increase when sleep_quality was added? Test whether this increase is statistically significant, showing the two models being compared, their residual sums of squares (or \(R^2\) values) and degrees of freedom, the resulting \(F\)-statistic, and the \(p\)-value. Do not simply quote software output without showing how the pieces fit together.
  3. A student in your study group says: “Once you control for sleep quality, study hours no longer matters.” Using the coefficients from Model 2, explain why this claim is incorrect.

Part D – Research question 3: is workshop attendance associated with exam performance, controlling for study time and sleep quality?

  1. Add workshop to the model as a dummy-coded predictor (Model 3). State explicitly which category is coded 0 and which is coded 1, and what the model’s intercept now represents given that coding.
  2. Report the coefficient for workshop, its significance test, and the increase in \(R^2\) over Model 2 (with the supporting \(F\)-test, as in Question 8).
  3. Compute standardized regression coefficients for the continuous predictors in Model 3. Which of study_hours and sleep_quality has the larger standardized effect on exam_score? Why is a standardized coefficient not calculated, or interpreted, in quite the same way for the workshop dummy variable?

Part E – Checking the model

  1. Using Model 3, produce the four standard diagnostic plots (residuals vs. fitted, normal Q-Q, scale-location, residuals vs. leverage) and the diagnostic statistics from the code above. For each of the LINE assumptions – Linearity, Independence, Normality, Homoscedasticity – state, using the checks introduced in lecture, whether the model supports the assumption.
  2. One student’s residual is noticeably larger in magnitude than the rest. Identify this student by student_id. Is this observation unduly influential on the regression results? Support your answer with an appropriate influence statistic, not the residual alone.

Part F – Research question 4: does the benefit of study time depend on workshop attendance? (moderation)

  1. Extend Model 3 by adding the interaction between study_hours and workshop (Model 4). Report the coefficients, and test whether adding the interaction improves the model significantly over Model 3.
  2. Using the Model 4 coefficients, compute the simple slope of study_hours on exam_score separately for students who did and did not attend the workshop. Explain, in substantive terms a programme coordinator would understand, what these two slopes mean.
  3. Plot predicted exam score against study hours as two lines, one per workshop group. Does the pattern support treating workshop attendance as a moderator of the study-hours effect, or would an interaction-free model (Model 3) have told the coordinator everything worth knowing?

Part G – Reporting

  1. Write a short paragraph, as it might appear in the results section of a report to the programme coordinator, summarizing what you can and cannot conclude about the value of the exam-prep workshop from this analysis. Be explicit about the observational nature of workshop attendance (students were not randomly assigned to attend).

3 Guided Walkthrough

This walkthrough works through the exam-performance scenario from start to finish: understanding the problem, inspecting the data, choosing a method, conducting the analysis, examining the output, interpreting it, and reporting it. The reasoning matters more than the numbers themselves.

3.1 Understanding the problem

The programme coordinator’s real concern has three layers. First, does study time predict exam performance at all. Second, does sleep quality add anything once study time is accounted for. Third, and most importantly, is workshop attendance associated with exam performance once study time and sleep quality are already in the model, and does the workshop’s apparent benefit hold up, or even grow, once we allow for the possibility that the workshop changes how much studying helps a student rather than simply adding a flat bonus. Each of these is a separate research question, and each should be answered by adding exactly one thing to the model and asking what changed.

3.2 Inspecting the data

d <- read.csv("data/exam_performance_lab.csv", stringsAsFactors = TRUE)
d$workshop <- relevel(d$workshop, ref = "No Workshop")
str(d)
## 'data.frame':    150 obs. of  5 variables:
##  $ student_id   : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ study_hours  : num  5.7 9.2 4.8 7.6 4.3 8.9 8.6 8.8 10.7 8.2 ...
##  $ sleep_quality: num  2.9 6.4 8.5 8 5.7 4.7 7 4.3 5.1 6.6 ...
##  $ workshop     : Factor w/ 2 levels "No Workshop",..: 1 1 2 1 1 1 2 1 1 1 ...
##  $ exam_score   : num  67.5 71.7 62 73.7 51.4 62.3 100 73.6 76.4 78.9 ...
d %>%
  group_by(workshop) %>%
  summarise(n = n(),
            study_hours_M = mean(study_hours), study_hours_SD = sd(study_hours),
            sleep_quality_M = mean(sleep_quality), sleep_quality_SD = sd(sleep_quality),
            exam_score_M = mean(exam_score), exam_score_SD = sd(exam_score)) %>%
  kable()
workshop n study_hours_M study_hours_SD sleep_quality_M sleep_quality_SD exam_score_M exam_score_SD
No Workshop 84 7.955 2.751 6.204 1.664 66.45 10.73
Workshop 66 8.114 3.088 6.370 1.372 82.35 14.36

The two groups look similar on study hours and sleep quality, but very different on exam score. That is exactly the pattern that makes the coordinator’s question worth asking properly: a raw difference in exam score of that size is not, on its own, evidence that the workshop caused anything, since students were not randomly assigned to attend it.

ggplot(d, aes(study_hours, exam_score, color = workshop)) +
  geom_point(alpha = 0.75) +
  scale_color_manual(values = c("No Workshop" = "grey40", "Workshop" = ntnublue)) +
  labs(x = "Weekly study hours", y = "Exam score",
       title = "Study hours and exam score, by workshop attendance", color = NULL)

The scatterplot shows a positive relationship in both groups, with the workshop group sitting visibly above the no-workshop group across most of the range of study hours.

cor(d$study_hours, d$sleep_quality)
## [1] 0.1638

This is a small correlation. It means study_hours and sleep_quality are close to independent sources of information about exam performance, so entering both into the same model should not create serious collinearity, and each coefficient in Model 2 and beyond can be read as close to what it would be if the other predictor were absent. This will be confirmed formally with a variance inflation factor (VIF) below.

3.3 Identifying the appropriate method

Every research question here concerns a continuous outcome (exam_score), and the questions build on each other by adding one predictor at a time and asking whether it changes the picture. That is exactly the setting for a sequence of nested multiple regression models, compared using the \(R^2\) change and its associated \(F\)-test at each step. The categorical predictor (workshop) enters as a single dummy variable, since it has only two levels. The fourth question, about whether the study-hours effect differs by workshop attendance, calls for a product (interaction) term between a continuous predictor and a dummy predictor.

3.4 Model 1 – does weekly study time predict exam performance?

m1 <- lm(exam_score ~ study_hours, data = d)
summary(m1)
## 
## Call:
## lm(formula = exam_score ~ study_hours, data = d)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -28.838  -7.888  -0.377   7.863  26.285 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   47.522      2.752    17.3   <2e-16 ***
## study_hours    3.231      0.323    10.0   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 11.4 on 148 degrees of freedom
## Multiple R-squared:  0.404,  Adjusted R-squared:   0.4 
## F-statistic:  100 on 1 and 148 DF,  p-value: <2e-16
confint(m1)
##              2.5 % 97.5 %
## (Intercept) 42.083 52.961
## study_hours  2.593  3.869

Every additional weekly study hour is associated with a 3.23-point increase in predicted exam score, on average. Study hours alone accounts for 40.4% of the variance in exam scores in this sample (\(R^2\) = 0.404). This is \(k = 1\) predictor.

3.5 Model 2 – does sleep quality explain exam performance beyond study time?

m2 <- lm(exam_score ~ study_hours + sleep_quality, data = d)
summary(m2)
## 
## Call:
## lm(formula = exam_score ~ study_hours + sleep_quality, data = d)
## 
## Residuals:
##    Min     1Q Median     3Q    Max 
## -27.25  -7.07   1.18   7.29  24.96 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)     38.661      4.314    8.96  1.3e-15 ***
## study_hours      3.093      0.321    9.64  < 2e-16 ***
## sleep_quality    1.589      0.603    2.63   0.0094 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 11.2 on 147 degrees of freedom
## Multiple R-squared:  0.431,  Adjusted R-squared:  0.423 
## F-statistic: 55.6 on 2 and 147 DF,  p-value: <2e-16
confint(m2)
##                 2.5 % 97.5 %
## (Intercept)   30.1360 47.186
## study_hours    2.4585  3.727
## sleep_quality  0.3963  2.781
anova(m1, m2)
## Analysis of Variance Table
## 
## Model 1: exam_score ~ study_hours
## Model 2: exam_score ~ study_hours + sleep_quality
##   Res.Df   RSS Df Sum of Sq    F Pr(>F)   
## 1    148 19259                            
## 2    147 18391  1       867 6.93 0.0094 **
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Adding sleep quality significantly improves the model (\(\Delta R^2\) = 0.027). Note that the study_hours coefficient barely moved, from 3.23 to 3.09: because study_hours and sleep_quality are only weakly correlated, controlling for sleep quality does not meaningfully change what study hours has to say about exam score. This is worth stating explicitly, because it is a common misreading: study hours does not “stop mattering” once sleep quality is in the model; its coefficient, its standard error, and its significance are all still essentially what they were in Model 1. Sleep quality is simply a second, largely independent predictor of exam performance.

3.6 Model 3 – is workshop attendance associated with exam performance, controlling for study time and sleep quality?

workshop is dummy-coded with “No Workshop” as the reference category (coded 0) and “Workshop” as the comparison category (coded 1), so the model intercept now represents the predicted exam score for a student who did not attend the workshop, has zero study hours, and zero sleep quality (an extrapolation beyond the observed data, as is often true of a raw intercept, but still the correct algebraic reading of the term).

m3 <- lm(exam_score ~ study_hours + sleep_quality + workshop, data = d)
summary(m3)
## 
## Call:
## lm(formula = exam_score ~ study_hours + sleep_quality + workshop, 
##     data = d)
## 
## Residuals:
##    Min     1Q Median     3Q    Max 
## -35.55  -5.39   0.29   5.59  19.02 
## 
## Coefficients:
##                  Estimate Std. Error t value Pr(>|t|)    
## (Intercept)        33.938      3.202   10.60   <2e-16 ***
## study_hours         3.043      0.236   12.89   <2e-16 ***
## sleep_quality       1.340      0.445    3.01    0.003 ** 
## workshopWorkshop   15.189      1.356   11.20   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 8.23 on 146 degrees of freedom
## Multiple R-squared:  0.694,  Adjusted R-squared:  0.687 
## F-statistic:  110 on 3 and 146 DF,  p-value: <2e-16
confint(m3)
##                    2.5 % 97.5 %
## (Intercept)      27.6092 40.267
## study_hours       2.5761  3.509
## sleep_quality     0.4613  2.218
## workshopWorkshop 12.5090 17.869
anova(m2, m3)
## Analysis of Variance Table
## 
## Model 1: exam_score ~ study_hours + sleep_quality
## Model 2: exam_score ~ study_hours + sleep_quality + workshop
##   Res.Df   RSS Df Sum of Sq   F Pr(>F)    
## 1    147 18391                            
## 2    146  9892  1      8500 125 <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Holding study hours and sleep quality constant, students who attended the workshop scored, on average, 15.19 points higher than students who did not. This is the coordinator’s key result: the workshop is associated with a large and highly significant difference in exam performance even after accounting for how much a student studied and how well a student slept, which addresses the original worry that the workshop’s apparent benefit was really just a stand-in for those two things.

lm.beta(m3)
## 
## Call:
## lm(formula = exam_score ~ study_hours + sleep_quality + workshop, 
##     data = d)
## 
## Standardized Coefficients::
##      (Intercept)      study_hours    sleep_quality workshopWorkshop 
##               NA           0.5984           0.1401           0.5138

Standardizing the continuous predictors puts study_hours and sleep_quality on a comparable scale: study hours has by far the larger standardized effect on exam score. lm.beta() still returns a number for workshop, but it is not meaningfully interpreted the same way as the continuous predictors’ standardized coefficients, because standardizing a 0/1 dummy variable rescales it by its own standard deviation, which depends only on the split between groups rather than on any meaningful unit of “amount of workshop.” The unstandardized coefficient – a group difference in points – is already the natural, interpretable scale for a categorical predictor and should be reported as such.

3.7 Checking the model before trusting it

A model is not ready to report until the assumptions behind its \(p\)-values and confidence intervals have been checked.

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

par(mfrow = c(1, 1))
durbinWatsonTest(m3)
##  lag Autocorrelation D-W Statistic p-value
##    1        -0.01892         2.009    0.96
##  Alternative hypothesis: rho != 0
shapiro.test(resid(m3))
## 
##  Shapiro-Wilk normality test
## 
## data:  resid(m3)
## W = 0.98, p-value = 0.02
vif(m3)
##   study_hours sleep_quality      workshop 
##         1.028         1.030         1.003
Assumption Check used Verdict
Linearity Residuals vs. Fitted No systematic curve; reasonable
Independence Durbin-Watson statistic Close to 2; reasonable
Normality of residuals Normal Q-Q plot; Shapiro-Wilk test Mild departure in the tail; check the printed \(p\)-value
Homoscedasticity (equal variance) Third diagnostic panel (Scale-Location) Spread of residuals looks roughly constant across fitted values; reasonable

If the Shapiro-Wilk test comes out significant, look at the Q-Q plot before concluding the model is unusable: with \(N = 150\), this test is sensitive enough to flag small departures that have little practical effect on the coefficients or their standard errors, especially when the departure traces to a bounded outcome (exam scores capped at 100) rather than a genuinely misspecified model. The variance inflation factors confirm what the small pairwise correlation already suggested: multicollinearity is not a concern in this model.

d$resid_m3 <- resid(m3)
d %>% arrange(resid_m3) %>%
  select(student_id, study_hours, sleep_quality, workshop, exam_score, resid_m3) %>%
  head(1) %>%
  kable()
student_id study_hours sleep_quality workshop exam_score resid_m3
106 3.5 5.8 Workshop 32 -35.55
cooks <- cooks.distance(m3)
sort(cooks, decreasing = TRUE)[1:5]
##     106      77       3       1     128 
## 0.16078 0.06314 0.02831 0.02713 0.02389

A large residual is worth a second look, but a large residual is not the same thing as an influential point. Compare the largest Cook’s distance above against the conventional concern threshold of 1.0: this student’s exam score is unusual, but removing this single observation would not materially change the conclusions drawn from Model 3.

3.8 Model 4 – does the benefit of study time depend on workshop attendance? (moderation)

m4 <- lm(exam_score ~ study_hours * workshop + sleep_quality, data = d)
summary(m4)
## 
## Call:
## lm(formula = exam_score ~ study_hours * workshop + sleep_quality, 
##     data = d)
## 
## Residuals:
##    Min     1Q Median     3Q    Max 
## -32.03  -4.45   0.03   5.20  18.24 
## 
## Coefficients:
##                              Estimate Std. Error t value Pr(>|t|)    
## (Intercept)                    38.785      3.430   11.31  < 2e-16 ***
## study_hours                     2.280      0.325    7.01  8.3e-11 ***
## workshopWorkshop                3.090      3.895    0.79  0.42890    
## sleep_quality                   1.537      0.434    3.54  0.00054 ***
## study_hours:workshopWorkshop    1.502      0.455    3.30  0.00122 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 7.97 on 145 degrees of freedom
## Multiple R-squared:  0.715,  Adjusted R-squared:  0.707 
## F-statistic:   91 on 4 and 145 DF,  p-value: <2e-16
confint(m4)
##                                2.5 % 97.5 %
## (Intercept)                  32.0060 45.563
## study_hours                   1.6369  2.922
## workshopWorkshop             -4.6085 10.789
## sleep_quality                 0.6788  2.396
## study_hours:workshopWorkshop  0.6022  2.402
anova(m3, m4)
## Analysis of Variance Table
## 
## Model 1: exam_score ~ study_hours + sleep_quality + workshop
## Model 2: exam_score ~ study_hours * workshop + sleep_quality
##   Res.Df  RSS Df Sum of Sq    F Pr(>F)   
## 1    146 9892                            
## 2    145 9201  1       691 10.9 0.0012 **
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

With an interaction in the model, study_hours and workshop no longer have simple, standalone interpretations; each is now a conditional effect. The study_hours coefficient is the simple slope of study hours specifically for students who did not attend the workshop (the reference group), and the workshop coefficient is the group difference specifically at study_hours = 0, which is not a substantively meaningful value here. This is a common point of confusion: it would be wrong to conclude from this table that “workshop attendance no longer matters,” since the workshop’s effect is now spread across the main-effect term and the interaction term together.

b <- coef(m4)
slope_no_workshop <- b[["study_hours"]]
slope_workshop <- b[["study_hours"]] + b[["study_hours:workshopWorkshop"]]
c(No_Workshop = slope_no_workshop, Workshop = slope_workshop)
## No_Workshop    Workshop 
##       2.280       3.782
sleep_mean <- mean(d$sleep_quality)
newdat <- expand.grid(
  study_hours = seq(min(d$study_hours), max(d$study_hours), length.out = 100),
  workshop = levels(d$workshop),
  sleep_quality = sleep_mean
)
newdat$predicted <- predict(m4, newdata = newdat)

ggplot(newdat, aes(study_hours, predicted, color = workshop)) +
  geom_line(linewidth = 1.2) +
  scale_color_manual(values = c("No Workshop" = "grey40", "Workshop" = ntnublue)) +
  labs(x = "Weekly study hours", y = "Predicted exam score",
       title = "Predicted exam score by study hours and workshop attendance",
       subtitle = "Sleep quality held at its sample mean", color = NULL)

Each additional weekly study hour is worth noticeably more for a student who attended the workshop than for one who did not. The workshop does not just add a flat bonus to every student’s score; it appears to make studying itself more effective, which is a substantively richer and, for a programme coordinator deciding whether to keep funding the workshop, more useful finding than a flat group difference alone.

3.9 Interpreting the findings

Taken together, the four models answer the coordinator’s question in stages. Study time predicts exam performance on its own. Sleep quality adds a further, largely independent contribution. Workshop attendance is associated with substantially higher exam scores even after both of those are held constant, ruling out the concern that the workshop’s apparent benefit was just a proxy for already-motivated, well-rested students. Model 4 goes one step further and shows that the workshop’s benefit is not simply additive: it appears to amplify the payoff from studying, a pattern a flat group-difference model would have missed entirely.

3.10 Reporting the results

Weekly study hours significantly predicted exam performance (Model 1). Sleep quality added a small but significant additional contribution (Model 2). Attendance at a voluntary exam-preparation workshop was associated with substantially higher exam scores after accounting for study hours and sleep quality (Model 3), and this association held even though workshop attenders and non-attenders did not differ appreciably in study hours or sleep quality, which argues against the possibility that the workshop’s benefit was solely attributable to those two factors. A significant study-hours by workshop interaction (Model 4) indicated that the benefit of additional study time was larger for students who attended the workshop than for those who did not. Because workshop attendance was voluntary rather than randomly assigned, these results are consistent with, but do not by themselves establish, a causal benefit of the workshop.

4 Solutions

Expected answers to the Questions above. The reasoning for each is in the Guided Walkthrough section; this section states the answers directly, reusing the models already fitted there.

Part A

  1. 150 students overall (84 No Workshop, 66 Workshop). See the descriptives table under Inspecting the data above.
  2. The relationship between study hours and exam score is positive in both groups, and roughly linear. The workshop group sits visibly above the no-workshop group across most of the range of study hours, suggesting a group difference in exam score beyond whatever is explained by study hours alone.
  3. 0.164. This is small: it means the two predictors carry largely separate information about exam score, so their multiple-regression coefficients can each be read as close to that predictor’s own, unshared contribution, rather than being distorted by shared overlap with the other predictor (multicollinearity), confirmed by the VIF check in Part E.

Part B

  1. Model 1: intercept = 47.52, slope for study_hours = 3.23, \(R^2\) = 0.404.
  2. Each additional hour of weekly study is associated with, on average, a 3.23-point increase in exam score.
  3. Significant – see the summary(m1) output above for the exact \(t\), \(df\), and \(p\).

Part C

  1. Model 2: intercept = 38.66, study_hours = 3.09, sleep_quality = 1.59, \(R^2\) = 0.431.
  2. \(\Delta R^2\) = 0.027. See the anova(m1, m2) output above for the residual sums of squares, \(df\), \(F\), and \(p\) underlying this test – do not just quote the final numbers, show the comparison.
  3. The claim is incorrect. The study_hours coefficient in Model 2 is almost identical to its value in Model 1, and it remains highly significant. Study hours continues to matter once sleep quality is controlled for; the two predictors are only weakly correlated, so adding sleep quality does not meaningfully change what study hours contributes.

Part D

  1. “No Workshop” is coded 0 (the reference category) and “Workshop” is coded 1. The Model 3 intercept represents the predicted exam score for a student who did not attend the workshop and has zero study hours and zero sleep quality.
  2. Workshop coefficient = 15.19. See the summary(m3) and anova(m2, m3) output above for the test statistics and \(\Delta R^2\).
  3. See the lm.beta(m3) output above. Study hours has the larger standardized effect. A standardized coefficient is not interpreted the same way for workshop, because standardizing a 0/1 dummy divides by a standard deviation that depends only on the size of the two groups, not on any meaningful unit of “workshop”; the unstandardized group difference is already the natural way to report a categorical predictor’s effect.

Part E

  1. See the diagnostic plots and test statistics above (Checking the model before trusting it): linearity, independence, and equal variance all look reasonable; normality shows a mild, explainable departure.
  2. See the largest residual chunk above: the student with the largest-magnitude residual has a Cook’s distance far below the conventional concern threshold of 1.0, so this observation is unusual but not unduly influential.

Part F

  1. Model 4 adds study_hours:workshop – see the summary(m4) and anova(m3, m4) output above. The interaction significantly improves the model.
  2. See the simple slopes chunk above: for students who did not attend the workshop, each extra weekly study hour is worth the No_Workshop value in exam points; for students who did attend, it is worth the (larger) Workshop value. The workshop does not just add a flat score bonus, it appears to make each hour of studying more productive.
  3. The two predicted lines (plotted above) start close together at low study hours and fan apart as study hours increase, which is the signature pattern of a genuine interaction. An interaction-free model (Model 3) would have told the coordinator that workshop attenders score higher on average, but it would have missed the fact that the workshop’s payoff grows with how much a student studies.

Part G

  1. Example paragraph:

Study hours, sleep quality, and attendance at a voluntary exam-preparation workshop were entered in a sequence of regression models predicting exam score. All three predictors were independently associated with higher exam performance, and workshop attendance remained a large, significant predictor even after accounting for study hours and sleep quality, arguing against the possibility that its apparent benefit was solely a proxy for already better-prepared or better-rested students. A significant interaction further indicated that the benefit of additional study time was greater among workshop attenders than non-attenders. Because students self-selected into the workshop rather than being randomly assigned, these findings are consistent with a benefit of the workshop but cannot, on their own, establish that attending the workshop caused the improvement in exam scores; unmeasured differences between the kinds of students who choose to attend and those who do not (for example, motivation or exam anxiety) remain a plausible alternative explanation.

Common errors and points to watch for

sessionInfo()
## R version 4.4.2 (2024-10-31)
## Platform: aarch64-apple-darwin20
## Running under: macOS 26.6.2
## 
## Matrix products: default
## BLAS:   /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRblas.0.dylib 
## LAPACK: /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.12.0
## 
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
## 
## time zone: Europe/Oslo
## tzcode source: internal
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] knitr_1.51      car_3.1-5       carData_3.0-6   lm.beta_1.7-3   lubridate_1.9.5 forcats_1.0.1   stringr_1.6.0  
##  [8] dplyr_1.2.0     purrr_1.2.1     readr_2.2.0     tidyr_1.3.2     tibble_3.3.1    ggplot2_4.0.2   tidyverse_2.0.0
## [15] pacman_0.5.1   
## 
## loaded via a namespace (and not attached):
##  [1] gtable_0.3.6       jsonlite_2.0.0     compiler_4.4.2     tidyselect_1.2.1   jquerylib_0.1.4    scales_1.4.0      
##  [7] yaml_2.3.12        fastmap_1.2.0      R6_2.6.1           labeling_0.4.3     generics_0.1.4     Formula_1.2-5     
## [13] tzdb_0.5.0         bslib_0.10.0       pillar_1.11.1      RColorBrewer_1.1-3 rlang_1.1.7        stringi_1.8.7     
## [19] cachem_1.1.0       xfun_0.57          sass_0.4.10        S7_0.2.1           otel_0.2.0         timechange_0.4.0  
## [25] cli_3.6.5          withr_3.0.2        magrittr_2.0.4     digest_0.6.39      grid_4.4.2         xtable_1.8-8      
## [31] rstudioapi_0.18.0  hms_1.1.4          lifecycle_1.0.5    vctrs_0.7.2        evaluate_1.0.5     glue_1.8.0        
## [37] farver_2.1.2       abind_1.4-8        rmarkdown_2.30     tools_4.4.2        pkgconfig_2.0.3    htmltools_0.5.9