Uma variável de resposta y é uma função não linear de várias variáveis preditoras X (nos meus dados reais a resposta é distribuída binomialmente, mas aqui estou usando um valor normalmente distribuído para simplificar). Posso modelar os relacionamentos entre os preditores e a resposta usando splines / smooths (por exemplo, modelos GAM no mgcv
pacote em R).
Por enquanto, tudo bem. No entanto, cada resposta é o resultado de processos que evoluem ao longo do tempo. Ou seja, a relação entre os preditores X e a resposta y muda ao longo do tempo. Para cada resposta, tenho dados para os preditores ao longo de vários pontos no tempo em torno da resposta. Ou seja, há uma resposta por grupo de pontos no tempo (não que a resposta evolua ao longo do tempo).
Algumas ilustrações são provavelmente úteis neste momento. Aqui estão alguns dados com parâmetros conhecidos (código abaixo) e plotados usando o ggplot2 (especificando o método GAM e um método mais suave apropriado), com o tempo nas facetas. Por ilustração, y é uma função quadrática de x1, e o sinal e a magnitude dessa relação mudam em função do tempo.
A relação entre x2 e y é circular, correspondendo a um aumento em y com uma certa direção de x2. A amplitude dessa relação modula-se ao longo do tempo. (Modelado no ggplot usando um gam que especifica uma suavidade cúbica circular "cc").
Eu gostaria de modelar a mudança (não-linear) em cada preditor em função do tempo usando algo como um spline bidimensional.
Eu considerei o uso de uma suavização bidimensional no pacote mgcv (algo como te(x1,t)
), exceto que isso exigiria os dados de forma longa (ou seja, uma única coluna de pontos no tempo). Eu acho que isso é inadequado, porque uma resposta está associada a todos os pontos do tempo - portanto, organizar os dados em formato longo (duplicando a mesma resposta em várias linhas da matriz de design) violaria a independência das observações. Meus dados estão atualmente organizados com colunas (y, x1.t1, x1.t2, x1.t3, ..., x2.t1, x2.t2, ...)
e acho que esse é o formato mais apropriado.
Eu gostaria de saber:
- existe uma maneira melhor de modelar esses dados
- Nesse caso, como seria a matriz / fórmula de design do modelo. Por fim, gostaria de estimar os coeficientes do modelo usando a inferência bayesiana em um pacote mcmc como o JAGS, então gostaria de saber como escrever um spline bidimensional.
Código R para reproduzir meu exemplo:
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