Tell me more ×
Cross Validated is a question and answer site for statisticians, data analysts, data miners and data visualization experts. It's 100% free, no registration required.

(cross-posted from the R-sig ME list - maybe this is too basic for it)

Hello I would like to fit piecewise linear growth curves to a number of subjects (each with a number of observations at different abscissa), where all the slopes for a common interval (e.g, 2 <= x < 3) presumable arise from the same normal distribution, and therefore should be "shrunk" towards each other. What is the best way to about doing this in lme4? I have a toy, cleaned up (although I am not very good with R) example of the type of data I am looking at. Thank you for your time

set.seed(1)
# our growth functions are piecewise linear with these breaks
breaks <- seq(0,5)
mean.slopes <- seq(5,2,-.6)

# generate the true slope parameters for 20 subjects (variance isn't
    really constant or known, just simplifying)...
true.slopes <- sapply(mean.slopes,function(x) rnorm(n=20,sd=3,mean=x))

# ...and the intercepts - they really don't come from any particular
    distribution
true.intercepts <- runif(n=20,min=30,max=50)

# generate sample data - we don't necessarily have the same number of
observations per subject
mat <- matrix(nr=20*10,nc=3)
for (i in 1:20)
{
   xs <- runif(n=10,min=0,max=6)
   slopes <- true.slopes[i,]
   ys <- true.intercepts[i] + rnorm(n=10,mean=0,sd=0.9) +
   sapply(xs, function(x) sum(slopes[1:floor(x)]) + (x - floor(x)) *
   slopes[ceiling(x)])
   id <- rep(i,10)
   mat[(1+10*(i-1)):(10*i),] <- cbind(xs,ys,id)
}
mat <- as.data.frame(mat)
names(mat) <- c("x","y","id")
# qplot(x=x,y=y,colour=as.factor(id),data=mat)

Eventually I might like to shrink the slopes for each individual towards each other, in the sense that if for a given subject the slope in the interval [2,3) is very small compared to the slopes of other subjects in the same interval, then the same would hold for the slope in [1,2), but I would like to get the basics first.

share|improve this question

1 Answer

Apologies for only posting code with no comments. I wrote this but don't have time now to comment and decided it was best to save this here and comment later.

# packages needed
library(lattice)
library(latticeExtra)
library(lme4)

# make a picture of the data
mat <- mat[order(mat$id, mat$x),]
mat$id <- factor(mat$id)
plot1 <- xyplot(y~x, group=id, data=mat, type="b")
plot1

# function to set up knots
knot <- function(x, knot) {(x-knot)*(x>knot)}
knots <- function(x, knots) {
  out <- sapply(knots, function(k) knot(x, k))
  colnames(out) <- knots
  out
}

# add knots to data frame
mat$knot <- knots(mat$x, 0:5)

# piecewise curves with no random effects
m1 <- lm(y~ knot, data=mat)
summary(m1)

# get predicted values
matX <- data.frame(x=0:6)
matX$knot <- knots(matX$x, 0:5)
matX$predict <- predict(m1, newdata=matX)

# plot of data and predicted values
plot1 <- xyplot(y~x, group=id, data=mat, type="b")
plot2 <- xyplot(predict~x, data=matX, type="b", col="black", lwd=3)
plot1+plot2

# piecewise curves with random effects
m2 <- lmer(y~ knot + (knot|id), data=mat)
summary(m2)
ranef(m2)

# get predicted values
ids <- unique(mat$id)
matXid <- expand.grid(id=unique(mat$id), x=0:6)
matXid$knot <- knots(matXid$x, 0:5)
matXid$predict <- rowSums(as.matrix(coef(m2)$id[matXid$id,]) * cbind(1,matXid$knot))

# plot of data and predicted values
plot1 <- xyplot(y~x|id, data=mat, type="b", as.table=TRUE)
plot2 <- xyplot(predict~x|id, data=matXid, type="b", col="black", lwd=1)
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.