Una variable de respuesta y es una función no lineal de varias variables predictoras X (en mis datos reales la respuesta está distribuida binomialmente, pero aquí estoy usando un valor normalmente distribuido para simplificar). Puedo modelar las relaciones entre los predictores y la respuesta usando splines / smooths (por ejemplo, modelos GAM en el mgcv
paquete en R).
Hasta aquí todo bien. Sin embargo, cada respuesta es el resultado de procesos que evolucionan con el tiempo. Es decir, la relación entre los predictores X y la respuesta y cambia con el tiempo. Para cada respuesta, tengo datos para los predictores en varios puntos de tiempo alrededor de la respuesta. Es decir, hay una respuesta por grupo de puntos de tiempo (no es que la respuesta evolucione con el tiempo).
Algunas ilustraciones son probablemente útiles en este punto. Aquí hay algunos datos con parámetros conocidos (código a continuación) y luego graficados usando ggplot2 (especificando el método GAM y un suavizador apropiado), con tiempo en las facetas. Por ejemplo, y es una función cuadrática de x1, y el signo y la magnitud de esta relación cambian en función del tiempo.
La relación entre x2 e y es circular, correspondiente a un aumento en y con una cierta dirección de x2. La amplitud de esta relación se modula con el tiempo. (Modelado en ggplot usando un gam que especifica un suavizador cúbico circular "cc").
Me gustaría modelar el cambio (no lineal) en cada predictor en función del tiempo usando algo así como una spline bidimensional.
He considerado usar un suavizado bidimensional en el paquete mgcv (algo así como te(x1,t)
), excepto que esto requeriría los datos en una forma larga (es decir, una sola columna de puntos de tiempo). Creo que esto es inapropiado, porque una respuesta está asociada con todos los puntos de tiempo, por lo que organizar los datos en forma larga (duplicando así la misma respuesta en múltiples filas de la matriz de diseño) violaría la independencia de las observaciones. Mis datos están actualmente organizados con columnas (y, x1.t1, x1.t2, x1.t3, ..., x2.t1, x2.t2, ...)
y creo que este es el formato más apropiado.
Me gustaría saber:
- ¿Hay alguna manera mejor de modelar estos datos?
- de ser así, cómo se vería la matriz / fórmula de diseño del modelo. En última instancia, me gustaría estimar los coeficientes del modelo utilizando la inferencia bayesiana en un paquete mcmc como JAGS, por lo que me gustaría saber cómo escribir una spline bidimensional.
Código R para reproducir mi ejemplo:
library(ggplot2)
library(mgcv)
#-------------------
# start by generating some data with known relationships between two variables,
# one periodic, over time.
set.seed(123)
nTimeBins <- 6
nSamples <- 500
# the relationship between x1, x2 and y are not linear.
# y = 0.4*x1^2 -1.2*x1 + 0.4*sin(x2) + 1.2*cos(x2)
# the relationship between x1, x2 and y evolve over time.
x1.timeMult <- cos(seq(-pi,pi,length=nTimeBins))
x2.timeMult <- cos(seq(-pi/2,pi/2,length=nTimeBins))
qplot(x=1:nTimeBins,y=x1.timeMult,geom="line") +
geom_line(aes(x=1:nTimeBins,y=x2.timeMult,colour="red")) +
guides(colour=FALSE) + ylab("multiplier")
df <- data.frame(setup=rep(NA,times=nSamples))
for (time in 1 : nTimeBins){
text <- paste('df$x1.t',time,' <- runif(nSamples,min=-3,max=3)',sep="")
eval(parse(text=text))
text <- paste('df$x2.t',time,' <- runif(nSamples,min=-pi,max=pi)',sep="")
eval(parse(text=text))
}
df$setup <- NULL
# each y is a function of x over time.
text <- 'y <- '
# replicated from above for reference:
# y = 0.4*x1^2 -1.2*x1 + 0.4*sin(x2) + 1.2*cos(x2)
for (time in 1 : nTimeBins){
text <- paste(text,'(0.4*x1.t',time,'^2-1.2*x1.t',time,') *
x1.timeMult[',time,'] + (0.4*sin(x2.t',time,') +
1.2*cos(x2.t',time,'))*x2.timeMult[',time,'] + ',sep="")
}
text <- paste(text,'rnorm(nSamples,sd=0.2)')
attach(df)
eval(parse(text=text))
df$y <- y
#-------------------
# transform into long form data for plotting:
df.long <- data.frame(y=rep(df$y,times=nTimeBins))
textX1 <- 'df.long$x1 <- c('
textX2 <- 'df.long$x2 <- c('
for (time in 1:nTimeBins){
textX1 <- paste(textX1,'x1.t',time,',',sep="")
textX2 <- paste(textX2,'x2.t',time,',',sep="")
}
textX1 <- paste(textX1,'NULL)',sep="")
textX2 <- paste(textX2,'NULL)',sep="")
eval(parse(text=textX1))
eval(parse(text=textX2))
# time stamp:
df.long$t <- factor(rep(1:nTimeBins,each=nSamples))
#-------------------
# plot relationships over time using GAM fits in ggplot:
p1 <- ggplot(df.long,aes(x=x1,y=y)) + geom_point() +
stat_smooth(method="gam",formula=y ~ s(x,bs="cs",k=4)) +
facet_wrap(~ t, ncol=3) + opts(title="x1 versus y over time")
p1
p2 <- ggplot(df.long,aes(x=x2,y=y)) + geom_point() +
stat_smooth(method="gam",formula=y ~ s(x,bs="cc",k=5)) +
facet_wrap(~ t, ncol=3) + opts(title="x2 versus y over time")
p2