随时间编码变化的截距和斜率之间的共线性 - 线性混合效应模型
Collinearity between intercept and slopes that vary by time coding - linear mixed effects model
我目前正在尝试 运行 线性混合效应模型来估计压力如何随时间(超过 6 个时间点)变化。我注意到,当为样本中的每个人提取应力轨迹的截距和斜率时,这些因素之间存在高度相关性。但是,这似乎会根据时间的编码方式而改变……对为什么会发生这种情况有任何解释吗?您通常如何处理截距和斜率之间的共线性?任何建议将不胜感激。
下面的可重现示例:
#toy data code: https://rpubs.com/mlmcternan/BC-lme
options(width = 100)
library(lme4)
library(nlme)
library(dplyr)
library(kableExtra)
library(psych)
library(car)
library(ggplot2)
library(ggpubr)
library(tidyverse)
set.seed(222)
# simulate data
N <- 150
nobs <- 6
sigma <- 20
sig00 <- 10
b0 <- 80
b1 <- -6
ID = rep(1:N, each = nobs)
# time is coded 0 to 5 here
Time = rep(0:5, 150)
dat <- data.frame(ID, Time)
u0 <- rnorm(N, 0, sig00)
dat$u0 <- rep(u0, each=nobs)
dat$err <- rnorm(900, 0, sigma)
dat$Stress <- (b0 + u0) + b1*dat$Time + dat$err
dat <- dat[,-c(3:4)]
# fit the model
fit1 <- lme(Stress ~ Time, random=~Time|ID, data=dat, correlation=corCAR1(form=~Time|ID), method="ML",na.action=na.exclude, control=list(opt="optim"))
# extract predictions
predictions <- data.frame(coef(fit1))
names(predictions) <- c("Intercept", "Slope")
# correlate intercept and slope
cor.test(predictions$Intercept, predictions$Slope, method = "pearson")
# Correlation between Intercept and Slope = 0.8057988
# plot correlation
plot(predictions$Intercept, predictions$Slope, main="Scatterplot Example",
xlab="Intercept ", ylab="Slope ", pch=19)
# Recode time - 0 represents predicted mean at timepoint 2
dat$Time <- rep(-1:4, 150)
fit1 <- lme(Stress ~ Time, random=~Time|ID, data=dat, correlation=corCAR1(form=~Time|ID), method="ML",na.action=na.exclude, control=list(opt="optim"))
predictions <- data.frame(coef(fit1))
names(predictions) <- c("Intercept", "Slope")
cor.test(predictions$Intercept, predictions$Slope, method = "pearson")
#correlation between intercept and slope = 0.6314682
plot(predictions$Intercept, predictions$Slope, main="Scatterplot Example",
xlab="Intercept ", ylab="Slope ", pch=19)
这更像是一个 statistics/math 问题,而不是关于编码的问题。无论如何,我认为你的不同相关性的原因是你 define/simulate 数据的方式根深蒂固。
使用意大利面条图查看(两个版本的)模拟数据:
library(ggplot2)
ggplot(dat, aes(y = Stress, x = Time, colour=as.factor(ID) )) +
geom_smooth(method=lm, se=FALSE) + theme(legend.position = "none") +
geom_vline(xintercept=0)
您会看到每个 ID 的回归线在图的中间(Time == 2.5
附近)比两端靠得更近。这是因为 b1*Time
对于较大的 abs(Time)
值更大。
现在,当您将 Time
的编码方式从 0 - 5 更改为 -1 - 4 时,您将 y 轴向右移动,线条靠得更近。因为截距定义为 Stress
的值,其中回归线穿过 y 轴,移动 y 轴会使截距靠得更近。或者,换句话说,移动 y 轴会改变斜率对截距的影响。
这就是为什么当你有调节器 and/or 随机斜率时,通常建议将预测变量居中。它使截距的解释更容易。
我目前正在尝试 运行 线性混合效应模型来估计压力如何随时间(超过 6 个时间点)变化。我注意到,当为样本中的每个人提取应力轨迹的截距和斜率时,这些因素之间存在高度相关性。但是,这似乎会根据时间的编码方式而改变……对为什么会发生这种情况有任何解释吗?您通常如何处理截距和斜率之间的共线性?任何建议将不胜感激。
下面的可重现示例:
#toy data code: https://rpubs.com/mlmcternan/BC-lme
options(width = 100)
library(lme4)
library(nlme)
library(dplyr)
library(kableExtra)
library(psych)
library(car)
library(ggplot2)
library(ggpubr)
library(tidyverse)
set.seed(222)
# simulate data
N <- 150
nobs <- 6
sigma <- 20
sig00 <- 10
b0 <- 80
b1 <- -6
ID = rep(1:N, each = nobs)
# time is coded 0 to 5 here
Time = rep(0:5, 150)
dat <- data.frame(ID, Time)
u0 <- rnorm(N, 0, sig00)
dat$u0 <- rep(u0, each=nobs)
dat$err <- rnorm(900, 0, sigma)
dat$Stress <- (b0 + u0) + b1*dat$Time + dat$err
dat <- dat[,-c(3:4)]
# fit the model
fit1 <- lme(Stress ~ Time, random=~Time|ID, data=dat, correlation=corCAR1(form=~Time|ID), method="ML",na.action=na.exclude, control=list(opt="optim"))
# extract predictions
predictions <- data.frame(coef(fit1))
names(predictions) <- c("Intercept", "Slope")
# correlate intercept and slope
cor.test(predictions$Intercept, predictions$Slope, method = "pearson")
# Correlation between Intercept and Slope = 0.8057988
# plot correlation
plot(predictions$Intercept, predictions$Slope, main="Scatterplot Example",
xlab="Intercept ", ylab="Slope ", pch=19)
# Recode time - 0 represents predicted mean at timepoint 2
dat$Time <- rep(-1:4, 150)
fit1 <- lme(Stress ~ Time, random=~Time|ID, data=dat, correlation=corCAR1(form=~Time|ID), method="ML",na.action=na.exclude, control=list(opt="optim"))
predictions <- data.frame(coef(fit1))
names(predictions) <- c("Intercept", "Slope")
cor.test(predictions$Intercept, predictions$Slope, method = "pearson")
#correlation between intercept and slope = 0.6314682
plot(predictions$Intercept, predictions$Slope, main="Scatterplot Example",
xlab="Intercept ", ylab="Slope ", pch=19)
这更像是一个 statistics/math 问题,而不是关于编码的问题。无论如何,我认为你的不同相关性的原因是你 define/simulate 数据的方式根深蒂固。
使用意大利面条图查看(两个版本的)模拟数据:
library(ggplot2)
ggplot(dat, aes(y = Stress, x = Time, colour=as.factor(ID) )) +
geom_smooth(method=lm, se=FALSE) + theme(legend.position = "none") +
geom_vline(xintercept=0)
您会看到每个 ID 的回归线在图的中间(Time == 2.5
附近)比两端靠得更近。这是因为 b1*Time
对于较大的 abs(Time)
值更大。
现在,当您将 Time
的编码方式从 0 - 5 更改为 -1 - 4 时,您将 y 轴向右移动,线条靠得更近。因为截距定义为 Stress
的值,其中回归线穿过 y 轴,移动 y 轴会使截距靠得更近。或者,换句话说,移动 y 轴会改变斜率对截距的影响。
这就是为什么当你有调节器 and/or 随机斜率时,通常建议将预测变量居中。它使截距的解释更容易。