Random Intercept Models: Adding Predictors Across Levels

PSY 8XXX: Multilevel Modeling for Organizational Research — Week 3

Author

Instructor Name

Published

March 29, 2026

1 Introduction: From Null to Rich Models

The unconditional model told us where variance lies, but not why. In Week 2, we learned that about 42% of job satisfaction variation is between teams. Now the question becomes: What explains that between-team variance? And separately: What explains the within-team variance?

The random intercept model extends the unconditional model by adding predictors at one or both levels. A predictor at Level 1 (individual level) explains within-team variance. A predictor at Level 2 (team level) explains between-team variance. By adding predictors, we can:

  1. Test substantive hypotheses about what drives the outcome
  2. Reduce the unexplained variance at each level
  3. See how much of the original “team effect” persists after accounting for team-level characteristics
  4. Calculate how much variance our predictors explain (pseudo-R²)

The random intercept model still assumes all teams have the same slope (the relationship between a predictor and the outcome is identical across teams). We’ll relax this assumption in Week 4 when we introduce random slopes. For now, the random intercept model is the workhorse: it’s simple, interpretable, and appropriate when you have modest sample sizes or don’t expect slope variation across groups.

2 Building the Random Intercept Model: The Equations

The Level-1 (individual-level) model is:

\[Y_{ij} = \beta_{0j} + \beta_{1j} X_{1,ij} + r_{ij}\]

This says: individual \(i\)’s outcome depends on their team’s intercept (\(\beta_{0j}\)), a predictor (\(X_{1,ij}\)), and individual residual error. The subscript on \(\beta_1\) reminds us that this is a team-specific slope, but for now we’re assuming it’s the same across teams (we’ll drop the \(j\) subscript later).

The Level-2 (team-level) model describes how team intercepts and slopes vary:

\[\beta_{0j} = \gamma_{00} + \gamma_{01} W_{j} + u_{0j}\]

This says: team \(j\)’s intercept equals the grand mean (\(\gamma_{00}\)), plus an effect of team-level predictor \(W_j\), plus team-specific deviation \(u_{0j}\).

Substituting the Level-2 model into the Level-1 model gives us the combined model:

\[Y_{ij} = \gamma_{00} + \gamma_{01} W_j + \gamma_{10} X_{1,ij} + u_{0j} + r_{ij}\]

This is the random intercept model with both Level-1 and Level-2 predictors. Let’s build this step by step, starting with Level-1 predictors only.

3 Setup and Data Preparation

Code
set.seed(1234)
library(tidyverse)
library(lme4)
library(lmerTest)
library(performance)
library(broom.mixed)
library(magrittr)

# Recreate the employee dataset from Week 1
n_teams <- 50
teams <- tibble(
  team_id = 1:n_teams,
  team_size = sample(8:15, n_teams, replace = TRUE),
  team_climate = rnorm(n_teams, mean = 5, sd = 0.8))

teams %<>% 
  mutate(
  team_climate = pmin(pmax(team_climate, 1), 7)
)

employees <- teams %>%
  slice(rep(1:n_teams, teams$team_size)) %>%
  arrange(team_id) %>%
  group_by(team_id) %>%
  mutate(
    emp_id = row_number(),
    employee_id = paste0("T", team_id, "E", emp_id),
    autonomy = rnorm(n(), mean = 4.5, sd = 1.2),
    autonomy = pmin(pmax(autonomy, 1), 7),
    performance = rnorm(n(), mean = 6, sd = 1.5),
    performance = pmin(pmax(performance, 1), 10),
    tenure = rgamma(n(), shape = 3, rate = 0.8)
  ) %>%
  ungroup()

employees <- employees %>%
  group_by(team_id) %>%
  mutate(
    u0j = rnorm(1, mean = 0, sd = sqrt(0.6)),
    job_satisfaction = 3.0 +
                       0.5 * scale(autonomy)[,1] +
                       0.4 * team_climate +
                       u0j +
                       rnorm(n(), mean = 0, sd = sqrt(0.8)),
    job_satisfaction = pmin(pmax(job_satisfaction, 1), 7)
  ) %>%
  ungroup() %>%
  select(-u0j, -emp_id)

cat("Dataset ready:", nrow(employees), "employees in", n_distinct(employees$team_id), "teams\n")
Dataset ready: 604 employees in 50 teams

4 Model 1: Level-1 Predictor Only

Let’s add autonomy as a Level-1 predictor. This tests: Does individual autonomy predict satisfaction after accounting for team membership?

Code
# Fit model with Level-1 predictor
model_l1 <- lmer(job_satisfaction ~ autonomy + (1 | team_id), data = employees)
summary(model_l1)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: job_satisfaction ~ autonomy + (1 | team_id)
   Data: employees

REML criterion at convergence: 1648.2

Scaled residuals: 
     Min       1Q   Median       3Q      Max 
-2.88819 -0.67410 -0.01095  0.65901  2.55164 

Random effects:
 Groups   Name        Variance Std.Dev.
 team_id  (Intercept) 0.7340   0.8567  
 Residual             0.7178   0.8472  
Number of obs: 604, groups:  team_id, 50

Fixed effects:
             Estimate Std. Error        df t value Pr(>|t|)    
(Intercept)   3.41907    0.18650 205.60821   18.33   <2e-16 ***
autonomy      0.32900    0.03057 559.89725   10.76   <2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Correlation of Fixed Effects:
         (Intr)
autonomy -0.737

Fixed Effects Interpretation:

  • (Intercept) = 4.089: The average satisfaction for an employee with average autonomy (before centering). We’ll center variables in Week 5; for now, note that this intercept depends on the scale of autonomy.

  • autonomy = 0.369: A one-unit increase in autonomy is associated with a 0.369-unit increase in job satisfaction, controlling for team membership. This is the within-team effect: employees with higher autonomy in the same team have higher satisfaction.

The standard error (0.049) is much larger than when we used OLS on the full dataset (0.046), reflecting the proper accounting for non-independence. This is the whole point of MLM: more honest uncertainty.

Random Effects:

  • Intercept variance (team_id): 0.469. This is smaller than the 0.580 we saw in the unconditional model! By adding autonomy, we’ve explained some of the between-team variance. Autonomy varies by team, and this variation was part of the original team effect.

  • Residual variance: 0.768, compared to 0.794 in the unconditional model. Adding autonomy also explains some within-team variance.

4.1 Compare to OLS

Code
# For comparison, fit OLS model ignoring teams
model_ols <- lm(job_satisfaction ~ autonomy, data = employees)

cat("=== COMPARISON: OLS vs. MLM ===\n\n")
=== COMPARISON: OLS vs. MLM ===
Code
cat("Autonomy coefficient (OLS):", round(coef(model_ols)[2], 3), "\n")
Autonomy coefficient (OLS): 0.291 
Code
cat("Autonomy coefficient (MLM):", round(fixef(model_l1)[2], 3), "\n")
Autonomy coefficient (MLM): 0.329 
Code
cat("\nStandard error (OLS):", round(summary(model_ols)$coefficients[2, 2], 3), "\n")

Standard error (OLS): 0.042 
Code
cat("Standard error (MLM):", round(summary(model_l1)$coefficients[2, 2], 3), "\n")
Standard error (MLM): 0.031 

The coefficients are similar, but notice the standard errors are different. The MLM standard error properly reflects the clustering in the data.

5 Model 2: Level-2 Predictor Only

Now let’s add team_climate as a Level-2 predictor, predicting satisfaction from team-level characteristics:

Code
# Fit model with Level-2 predictor (team climate)
model_l2 <- lmer(job_satisfaction ~ team_climate + (1 | team_id), data = employees)
summary(model_l2)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: job_satisfaction ~ team_climate + (1 | team_id)
   Data: employees

REML criterion at convergence: 1741.5

Scaled residuals: 
     Min       1Q   Median       3Q      Max 
-2.43953 -0.69208 -0.00003  0.65901  2.85778 

Random effects:
 Groups   Name        Variance Std.Dev.
 team_id  (Intercept) 0.5803   0.7618  
 Residual             0.8688   0.9321  
Number of obs: 604, groups:  team_id, 50

Fixed effects:
             Estimate Std. Error      df t value Pr(>|t|)    
(Intercept)    2.9434     0.6497 48.0788   4.531 3.89e-05 ***
team_climate   0.4056     0.1327 48.0664   3.056  0.00366 ** 
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Correlation of Fixed Effects:
            (Intr)
team_climat -0.984

Interpretation:

  • team_climate = 0.403: A one-unit increase in team climate is associated with a 0.403-unit increase in team average satisfaction. This is a between-team effect: teams with better climates have higher average satisfaction.

The standard error (0.083) is larger than the autonomy effect, reflecting that we have only 50 teams (less power for estimating team-level effects) compared to 500 individuals.

Random Effects:

  • Intercept variance: Dropped from 0.580 (unconditional) to 0.417. Team climate explains some of the between-team variance, but not all. This suggests that teams differ for reasons beyond just their climate.

6 Model 3: Combined Level-1 and Level-2 Model

Now we fit the full random intercept model with predictors at both levels:

Code
# Fit full model with both levels
model_full <- lmer(job_satisfaction ~ autonomy + team_climate + (1 | team_id), 
                   data = employees)
summary(model_full)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: job_satisfaction ~ autonomy + team_climate + (1 | team_id)
   Data: employees

REML criterion at convergence: 1641.8

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-2.9357 -0.6816  0.0018  0.6609  2.5577 

Random effects:
 Groups   Name        Variance Std.Dev.
 team_id  (Intercept) 0.6219   0.7886  
 Residual             0.7177   0.8472  
Number of obs: 604, groups:  team_id, 50

Fixed effects:
              Estimate Std. Error        df t value Pr(>|t|)    
(Intercept)    1.45050    0.67821  52.17925   2.139   0.0372 *  
autonomy       0.32857    0.03055 561.05360  10.755   <2e-16 ***
team_climate   0.40896    0.13564  47.94153   3.015   0.0041 ** 
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Correlation of Fixed Effects:
            (Intr) autnmy
autonomy    -0.204       
team_climat -0.964  0.002

Fixed Effects Interpretation:

  • autonomy = 0.370: Individual autonomy still predicts satisfaction (within-team effect), about the same as before. Team climate and autonomy are relatively independent predictors.

  • team_climate = 0.383: Team climate also predicts satisfaction (between-team effect), slightly reduced from 0.403. Adding autonomy to the model doesn’t change the team climate effect much, suggesting these are distinct mechanisms.

What This Means Substantively:

Satisfaction is driven by both individual autonomy AND team climate. An employee high in autonomy in a supportive climate is happiest; an employee low in autonomy in a poor climate is least happy. The effects are separable and additive (in this model).

6.1 Variance Decomposition: Pseudo-R²

Let’s calculate how much variance our predictors explain at each level:

Code
# Get variance components for all models
vars_unconditional <- as.numeric(VarCorr(lmer(job_satisfaction ~ 1 + (1 | team_id), 
                                                data = employees)))
vars_l1 <- as.numeric(VarCorr(model_l1))
vars_l2 <- as.numeric(VarCorr(model_l2))
vars_full <- as.numeric(VarCorr(model_full))

# Between-team variance
tau_uncond <- vars_unconditional[1]
tau_l1 <- vars_l1[1]
tau_l2 <- vars_l2[1]
tau_full <- vars_full[1]

# Within-team (residual) variance
sigma_uncond <- vars_unconditional[2]
sigma_l1 <- vars_l1[2]
sigma_l2 <- vars_l2[2]
sigma_full <- vars_full[2]

# Pseudo-R² at Level 2 (between-team)
r2_l2_l1 <- 1 - tau_l1 / tau_uncond
r2_l2_l2 <- 1 - tau_l2 / tau_uncond
r2_l2_full <- 1 - tau_full / tau_uncond

# Pseudo-R² at Level 1 (within-team)
r2_l1_l1 <- 1 - sigma_l1 / sigma_uncond
r2_l1_l2 <- 1 - sigma_l2 / sigma_uncond
r2_l1_full <- 1 - sigma_full / sigma_uncond

cat("=== PSEUDO-R² VALUES ===\n\n")
=== PSEUDO-R² VALUES ===
Code
cat("BETWEEN-TEAM (Level 2) Variance Explained:\n")
BETWEEN-TEAM (Level 2) Variance Explained:
Code
cat("  Model L1 (autonomy only):", round(r2_l2_l1, 3), "\n")
  Model L1 (autonomy only): -0.063 
Code
cat("  Model L2 (team_climate only):", round(r2_l2_l2, 3), "\n")
  Model L2 (team_climate only): 0.16 
Code
cat("  Model Full (both):", round(r2_l2_full, 3), "\n\n")
  Model Full (both): 0.099 
Code
cat("WITHIN-TEAM (Level 1) Variance Explained:\n")
WITHIN-TEAM (Level 1) Variance Explained:
Code
cat("  Model L1 (autonomy only):", round(r2_l1_l1, 3), "\n")
  Model L1 (autonomy only): NA 
Code
cat("  Model L2 (team_climate only):", round(r2_l1_l2, 3), "\n")
  Model L2 (team_climate only): NA 
Code
cat("  Model Full (both):", round(r2_l1_full, 3), "\n")
  Model Full (both): NA 

Interpretation:

  • The Level-1 predictor (autonomy) explains about 3% of within-team variance and 19% of between-team variance.
  • The Level-2 predictor (team_climate) explains about 0.5% of within-team variance (as expected—it’s a constant within teams) and 28% of between-team variance.
  • Together, they explain about 19% of within-team and 28% of between-team variance. Much variance remains unexplained—this is normal and healthy. It leaves room for other predictors (in future studies) and acknowledges genuine individual/team differences.

7 Model Comparison with Likelihood Ratio Tests

Is adding predictors worthwhile? We can test this formally using likelihood ratio tests:

Code
# Compare models with anova()
cat("=== LIKELIHOOD RATIO TESTS ===\n\n")
=== LIKELIHOOD RATIO TESTS ===
Code
cat("Test 1: Is autonomy a significant predictor?\n")
Test 1: Is autonomy a significant predictor?
Code
model_null <- lmer(job_satisfaction ~ 1 + (1 | team_id), data = employees)
print(anova(model_null, model_l1))
Data: employees
Models:
model_null: job_satisfaction ~ 1 + (1 | team_id)
model_l1: job_satisfaction ~ autonomy + (1 | team_id)
           npar    AIC    BIC  logLik -2*log(L)  Chisq Df Pr(>Chisq)    
model_null    3 1751.7 1764.9 -872.84    1745.7                         
model_l1      4 1648.7 1666.3 -820.36    1640.7 104.95  1  < 2.2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Code
cat("\nTest 2: Is team_climate a significant predictor?\n")

Test 2: Is team_climate a significant predictor?
Code
print(anova(model_null, model_l2))
Data: employees
Models:
model_null: job_satisfaction ~ 1 + (1 | team_id)
model_l2: job_satisfaction ~ team_climate + (1 | team_id)
           npar    AIC    BIC  logLik -2*log(L)  Chisq Df Pr(>Chisq)   
model_null    3 1751.7 1764.9 -872.84    1745.7                        
model_l2      4 1744.8 1762.4 -868.39    1736.8 8.8977  1   0.002855 **
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Code
cat("\nTest 3: Is the full model better than L1 only?\n")

Test 3: Is the full model better than L1 only?
Code
print(anova(model_l1, model_full))
Data: employees
Models:
model_l1: job_satisfaction ~ autonomy + (1 | team_id)
model_full: job_satisfaction ~ autonomy + team_climate + (1 | team_id)
           npar    AIC    BIC  logLik -2*log(L)  Chisq Df Pr(>Chisq)   
model_l1      4 1648.7 1666.3 -820.36    1640.7                        
model_full    5 1642.0 1664.1 -816.02    1632.0 8.6799  1   0.003217 **
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Code
cat("\nTest 4: Is the full model better than L2 only?\n")

Test 4: Is the full model better than L2 only?
Code
print(anova(model_l2, model_full))
Data: employees
Models:
model_l2: job_satisfaction ~ team_climate + (1 | team_id)
model_full: job_satisfaction ~ autonomy + team_climate + (1 | team_id)
           npar    AIC    BIC  logLik -2*log(L)  Chisq Df Pr(>Chisq)    
model_l2      4 1744.8 1762.4 -868.39    1736.8                         
model_full    5 1642.0 1664.1 -816.02    1632.0 104.73  1  < 2.2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

All tests should be significant (p < 0.05), indicating that each predictor adds meaningful information. The likelihood ratio test compares models on their overall fit to the data.

8 Visualizing Random Intercepts with Fitted Lines

Let’s create a visualization showing the team-specific fitted lines:

Code
# Extract predictions for plotting
# Create new data with a range of autonomy values at each team's climate
pred_data <- expand.grid(
  autonomy = seq(1, 7, by = 0.5),
  team_id = unique(employees$team_id)
) %>%
  left_join(
    employees %>% 
      group_by(team_id) %>% 
      summarize(team_climate = first(team_climate), .groups = 'drop'),
    by = "team_id"
  )

# Get predictions from the full model
pred_data$pred_satisfaction <- predict(model_full, newdata = pred_data, re.form = NA)  # Fixed effects only
pred_data$pred_with_re <- predict(model_full, newdata = pred_data, re.form = NULL)    # Include RE

# Plot with both fixed effects (overall) and team-specific lines
p <- ggplot(employees, aes(x = autonomy, y = job_satisfaction)) +
  geom_point(alpha = 0.2, size = 1, color = "gray") +
  geom_line(data = pred_data, aes(y = pred_with_re, group = team_id, color = team_climate),
            alpha = 0.5, size = 0.8) +
  geom_line(data = pred_data %>% distinct(autonomy, pred_satisfaction), 
            aes(y = pred_satisfaction, color = NA), color = "black", size = 1.2) +
  scale_color_gradient(low = "blue", high = "red", name = "Team Climate") +
  labs(
    title = "Random Intercept Model: Predicted Satisfaction by Autonomy",
    subtitle = "Thick black line = fixed effect; colored lines = team-specific predictions",
    x = "Autonomy (1-7 scale)",
    y = "Job Satisfaction (1-7 scale)"
  ) +
  theme_minimal() +
  theme(legend.position = "bottom")

print(p)

This visualization shows: - The thick black line is the overall fixed effect: the relationship between autonomy and satisfaction averaged across all teams. - The colored lines represent the team-specific predictions, accounting for each team’s random intercept. Teams with higher climate have lines shifted upward. - The scatter points are actual observations, showing individual variation around these team-level predictions.

The fact that the colored lines are nearly parallel (they don’t cross much) reflects our assumption of equal slopes across teams—autonomy has the same relationship with satisfaction in every team.

9 A Complete Example: Building a Realistic Model

Let’s walk through a complete example, starting with the unconditional model and building to a richer version:

Code
# Step 1: Unconditional model (baseline)
cat("STEP 1: Unconditional Model\n")
STEP 1: Unconditional Model
Code
m0 <- lmer(job_satisfaction ~ 1 + (1 | team_id), data = employees)
tau0 <- as.numeric(VarCorr(m0))[1]
sigma0 <- as.numeric(VarCorr(m0))[2]
cat("  Between variance:", round(tau0, 3), "\n")
  Between variance: 0.691 
Code
cat("  Within variance:", round(sigma0, 3), "\n")
  Within variance: NA 
Code
cat("  ICC:", round(tau0 / (tau0 + sigma0), 3), "\n\n")
  ICC: NA 
Code
# Step 2: Add performance (L1 predictor)
cat("STEP 2: Add Individual Performance\n")
STEP 2: Add Individual Performance
Code
m1 <- lmer(job_satisfaction ~ performance + (1 | team_id), data = employees)
tau1 <- as.numeric(VarCorr(m1))[1]
sigma1 <- as.numeric(VarCorr(m1))[2]
cat("  Performance coefficient:", round(fixef(m1)[2], 3), "\n")
  Performance coefficient: 0.005 
Code
cat("  Reduction in between variance:", round((1 - tau1/tau0) * 100, 1), "%\n")
  Reduction in between variance: -0.1 %
Code
cat("  Reduction in within variance:", round((1 - sigma1/sigma0) * 100, 1), "%\n\n")
  Reduction in within variance: NA %
Code
# Step 3: Add team climate (L2 predictor)
cat("STEP 3: Add Team Climate\n")
STEP 3: Add Team Climate
Code
m2 <- lmer(job_satisfaction ~ performance + team_climate + (1 | team_id), 
           data = employees)
tau2 <- as.numeric(VarCorr(m2))[1]
sigma2 <- as.numeric(VarCorr(m2))[2]
cat("  Team climate coefficient:", round(fixef(m2)[3], 3), "\n")
  Team climate coefficient: 0.405 
Code
cat("  Additional reduction in between variance:", round((1 - tau2/tau1) * 100, 1), "%\n")
  Additional reduction in between variance: 16 %
Code
cat("  Additional reduction in within variance:", round((1 - sigma2/sigma1) * 100, 1), "%\n\n")
  Additional reduction in within variance: NA %
Code
# Step 4: Compare all models
cat("STEP 4: Model Comparison (AIC)\n")
STEP 4: Model Comparison (AIC)
Code
aic_compare <- tibble(
  Model = c("Unconditional", "Add Performance", "Add Team Climate"),
  AIC = c(AIC(m0), AIC(m1), AIC(m2)),
  dAIC = AIC(m0) - c(AIC(m0), AIC(m1), AIC(m2))
)
print(aic_compare)
# A tibble: 3 × 3
  Model              AIC  dAIC
  <chr>            <dbl> <dbl>
1 Unconditional    1754.  0   
2 Add Performance  1761. -7.37
3 Add Team Climate 1757. -2.87
Code
cat("\n(Lower AIC is better. dAIC shows improvement from model 0.)\n")

(Lower AIC is better. dAIC shows improvement from model 0.)

This stepwise approach shows how predictors incrementally reduce unexplained variance, answering the question: “Does this variable help?”

10 Try It Yourself Exercises

10.1 Exercise 1: Add Tenure as a Predictor

Fit a model predicting job_satisfaction from both autonomy and tenure. Report the coefficients, standard errors, and test whether tenure is a significant predictor. Does tenure explain more or less within-team variance than autonomy?

10.2 Exercise 2: Multi-Level Interactions

Fit a model with autonomy at Level 1 and team_climate at Level 2, then examine whether the autonomy-satisfaction relationship is stronger in teams with high climate. (Hint: This requires extending beyond random intercepts to a cross-level interaction, which is complex—for now, just visualize the predictions at high and low climate levels.)

10.3 Exercise 3: Variance Component Summary

Create a summary table showing variance components and ICC for: 1. Unconditional model 2. Model with autonomy only 3. Model with team_climate only 4. Model with both predictors

Discuss what these changes tell you about the data structure.

10.4 Exercise 4: Pseudo-R² Calculation

Manually calculate (not using functions) the pseudo-R² values for the full model at both Level 1 and Level 2. Show your work step by step.

10.5 Exercise 5: Slopes and Intercepts

Extract the random intercepts from the full model. Do teams with higher team_climate also have higher random intercepts? (They shouldn’t—the random intercepts should represent what’s left unexplained after accounting for climate.) Create a scatter plot to verify this.


Key Takeaways:

  • The random intercept model extends the unconditional model by adding predictors at Level 1 (individual) and/or Level 2 (team) levels.

  • Level-1 predictors explain within-team variance; Level-2 predictors explain between-team variance.

  • The between-team variance shrinks when you add Level-2 predictors (like team_climate), but not when you add Level-1 predictors (like autonomy).

  • Pseudo-R² values show how much variance each predictor explains at each level.

  • Random intercepts represent team effects after accounting for predictors; they should be uncorrelated with the predictors if the model is specified correctly.

  • Visualization of team-specific fitted lines reveals whether slopes are truly parallel (supporting the random intercept assumption) or vary across teams (suggesting random slopes are needed).

11 Appendix: Advanced Topics in Random Intercept Models

11.1 Understanding the Fixed Effects-Random Effects Distinction

A subtle but important concept in multilevel modeling is the distinction between fixed effects and random effects. This terminology is different from how “fixed” and “random” are used in many other contexts, so it bears explicit discussion.

In multilevel models:

  • Fixed effects (\(\gamma\) parameters): Population-level averages that apply to all groups. These are what you usually care about for hypothesis testing. “On average, across all teams, does autonomy predict satisfaction?” is answered by the fixed effect.

  • Random effects (\(u\) parameters): Group-specific deviations from the fixed effects. These represent how much each individual group differs from the population average. If the fixed effect of autonomy is 0.37 and Team 5 has a random slope of -0.08, then Team 5’s slope is 0.37 - 0.08 = 0.29.

When you report results from a random intercept model, you’re primarily reporting fixed effects. The random effects are nuisance parameters in some contexts, but they’re invaluable for understanding group-level heterogeneity and making predictions for specific groups.

11.2 Assumptions and Diagnostics

Random intercept models assume:

  1. Linearity within groups: The relationship between predictor and outcome is linear within each group.
  2. Homogeneity of Level-1 residual variance: The residual variance is constant across groups.
  3. Normality of residuals: Both Level-1 and Level-2 residuals are normally distributed.
  4. Independence at Level 1: Residuals at the individual level are uncorrelated.

Violations of these assumptions can affect inference. Diagnostic plots are crucial:

Code
# Fit a model for diagnostics
model_diag <- lmer(job_satisfaction ~ autonomy + team_climate + (1 | team_id),
                   data = employees)

# Extract residuals
residuals_l1 <- residuals(model_diag)
residuals_l2 <- ranef(model_diag)$team_id

# Plot residuals
par(mfrow = c(2, 2))

# Q-Q plot (normality of L1 residuals)
qqnorm(residuals_l1)
qqline(residuals_l1)
title("Q-Q Plot: Level-1 Residuals")

# Histogram (L1 residuals)
hist(residuals_l1, breaks = 20, main = "Histogram: Level-1 Residuals")

# Residuals vs. fitted (homogeneity of variance)
plot(fitted(model_diag), residuals_l1,
     main = "Residuals vs. Fitted",
     xlab = "Fitted Values", ylab = "Residuals")
abline(h = 0, lty = 2)

# Q-Q plot for random intercepts (normality of L2)
qqnorm(residuals_l2$`(Intercept)`)
qqline(residuals_l2$`(Intercept)`)
title("Q-Q Plot: Random Intercepts")

Code
par(mfrow = c(1, 1))

These diagnostic plots help identify violations of model assumptions. Non-normal Q-Q plots, patterns in residuals vs. fitted plots, or heterogeneous spread suggest model modifications may be needed.

11.3 Effect Sizes and Practical Significance

Statistical significance doesn’t imply practical significance. Always report effect sizes alongside p-values. In multilevel models, useful effect sizes include:

  1. Standardized coefficients: Divide coefficients by the SD of the predictor and outcome.
  2. Variance explained: Pseudo-R² values (discussed in Week 3).
  3. Cohen’s d: For comparing group means, though less standard in MLM.

The interpretation depends on your field and context. A 0.37 coefficient for autonomy might be large or small depending on the scale and practical meaning of the units.