Loading some packages.

library(lmerTest)
library(ggplot2)
library(readr)
library(tidyverse)
library(pander)

The data

These are the data.

data <- read_csv("simpson.csv",col_types = "fdd")

ggplot(data,aes(Speed,Errors,group=Subject,colour=Subject)) +
  geom_point() +
  theme_minimal()

The question

The figure above suggests that there may be interesting between- and within-person effects in this dataset. How would you go about modeling these in the same regression model?

Three different approaches…

The first approach (lm) only captures the between-person effects…

# fixed effects model with lm
model1<-lm(Errors~Speed,data)
coefs<-coef(summary(model1))
pander(coefs)
  Estimate Std. Error t value Pr(>|t|)
(Intercept) 17.17 2.042 8.406 2.572e-08
Speed -1.433 0.3582 -4.001 0.0006016
datafit=fitted(model1)

ggplot(data,aes(Speed,Errors,group=Subject,colour=Subject)) +
  geom_point() +
  geom_line(aes(y=datafit))+
  geom_abline(intercept=coef(model1)[1],slope=coef(model1)[2])+
  theme_minimal()

A naive mixed-effects model captures within- and between-person effects without allowing a separate estimate of the two…

# mixed effects model with lmer
model2<-lmer(Errors~Speed+(Speed|Subject),data)
coefs<-coef(summary(model2))
pander(coefs)
  Estimate Std. Error df t value Pr(>|t|)
(Intercept) 2.512 3.146 4.651 0.7985 0.4634
Speed 1.865 0.4257 4.971 4.38 0.007249
datafit2=fitted(model2)
ggplot(data,aes(Speed,Errors,group=Subject,colour=Subject)) +
  geom_point() +
  geom_line(aes(y=datafit2))+
  geom_abline(intercept=fixef(model2)[1],slope=fixef(model2)[2],lty=2)+ 
  theme_minimal()

A simple procedure - within-subject centering - can be used to distinguish within- versus between- subject effects (cf. van de Pol & Wright, 2009)); in the plot below i plot both the within-person effects and the between-person effects estimated from the same model…

data_mod <- data %>% 
  group_by(Subject) %>% 
  mutate(Speed_mean=mean(Speed)) %>% 
  mutate(Speed_within=Speed-mean(Speed))

model3<-lmer(Errors~Speed_mean+Speed_within+(Speed_within|Subject),data_mod)
coefs<-coef(summary(model3))
pander(coefs)
  Estimate Std. Error df t value Pr(>|t|)
(Intercept) 18.89 1.807 4.357 10.45 0.0003008
Speed_mean -1.778 0.3119 4 -5.701 0.004678
Speed_within 1.9 0.4336 5 4.382 0.00714
datafit3=fitted(model3)
ggplot(data,aes(Speed,Errors,group=Subject,colour=Subject)) +
  geom_point() +
  geom_line(aes(y=datafit3))+ # plotting predictions by subject 
  geom_abline(intercept=fixef(model3)[1],slope=fixef(model3)[2])+ # plotting between-person effect
  geom_abline(intercept=0,slope=fixef(model3)[3],lty=2)+ # plotting between-person effect
  theme_minimal()