I'm working with multilevel models to try and describe different patterns in longitudinal change. Dingemanse et al (2010) describe a 'fanning out' pattern when the random effects are perfectly correlated. However I found that a similar pattern occurs when the relationship between random effects is non-linear but monotonically increasing over the observed interval. In this case random effects are not perfectly correlated but described by a function. See example below for an illustration of this. The example still has a high intercept-slope correlation (>.9) but it is possible to get correlations lower than .7 while still maintaining a perfect intercept-slope relation.
My question: Is there a way to include a perfect (non-linear) relationship between random effects in a multilevel model using nlme or some other R package? MLwiN has a way to constrain the slope-intercept covariance, that would be a start but is not sufficient to include non-linear relations. I've been unable to find solutions for nlme so far, but maybe you know of some other package that can include this in the model.
Apologies for the sloppy coding. I hope that my question is sufficiently clear but let me know if anything needs to be clarified. Any help or alternative solution is greatly appreciated.
set.seed(123456)
# Change function, quadratic
# Yit = B0ij + B1ij*time + B2ij*time^2
chn <- function(int, slp, slp2, time){
score<-int + slp * time+ slp2 * time^2
return(score)
}
# Set N, random intercept, time and ID
N<-100
start<-rnorm(N,100,15) # Random intercept
time<- matrix(1:15,ncol = 15, nrow = 100,byrow = T) # Time, balanced panel data
ID<-1:N # ID variable
# Random intercept, linear slope: exp(intercept/25)/75, quadratic slope: exp(intercept/25)/250
score3<-matrix(NA,ncol = ncol(time), nrow = N)
for(x in ID){
score3[x,]<-chn(start[x],exp(start[x]/25)/75,exp(start[x]/25)/250,time[x,])
}
#Create dataframe
df<- data.frame(ID,score3)
df2<- melt(df,id = 'ID')
df2$variable<-as.vector(time)
# plot
ggplot(df2, aes(x= variable, y= value)) + geom_line(aes(group = ID)) +
geom_smooth(method = "lm", formula = y ~ x + I(x^2), se =F, size = 2, col ="red" )
# Add noise and estimate model
df2$value2<-df2$value + rnorm(N*ncol(time),0,2)
# Random intercept
mod1<-lme(value2 ~ variable + I(variable^2),
random= list(ID = ~1),
data=df2,method="ML",na.action=na.exclude)
summary(mod1)
# Random slopes
mod2<-update(mod1,.~.,random= list(ID = ~variable + I(variable^2)))
summary(mod2)
pairs(ranef(mod2))