応答変数yは、いくつかの予測子変数Xの非線形関数です(実際のデータでは応答は二項分布ですが、ここでは簡単にするために正規分布値を使用しています)。スプライン/スムースを使用して、予測子と応答の間の関係をモデル化できます(たとえば、mgcv
R のパッケージのGAMモデル)。
ここまでは順調ですね。ただし、それぞれの応答は、時間とともに進化するプロセスの結果です。つまり、予測子Xと応答yの関係は、時間の経過とともに変化します。各応答について、応答の周りのいくつかの時点にわたる予測子のデータがあります。つまり、時点のグループごとに1つの応答があります(応答が時間とともに進化するわけではありません)。
この時点で、いくつかのイラストが役立つでしょう。以下は、既知のパラメーター(以下のコード)を持ついくつかのデータで、ggplot2(GAMメソッドと適切なスムーザーを指定)を使用して、ファセットの時間とともにプロットされます。説明のために、yはx1の2次関数であり、この関係の符号と大きさは時間の関数として変化します。
x2とyの関係は円形であり、特定の方向 x2 でのyの増加に対応します。この関係の振幅は、時間とともに変化します。(gcclotで、 "cc"円形3次スムーザーを指定するgamを使用してモデル化されています)。
2次元スプラインのようなものを使用して、各予測子の(非線形)変化を時間の関数としてモデル化したいと思います。
mgcvパッケージで2次元のスムース(のようなものte(x1,t)
)を使用することを検討しました。ただし、これには長い形式(つまり、1列の時点)のデータが必要になる場合を除きます。1つの応答がすべての時点に関連付けられているため、これは不適切だと思います-したがって、データを長い形式で配置すると(つまり、同じ応答を設計行列の複数の行に複製すると)、観測の独立性に違反します。私のデータは現在列(y, x1.t1, x1.t2, x1.t3, ..., x2.t1, x2.t2, ...)
で配置されており、これが最も適切なフォーマットだと思います。
私が知りたいのですが:
- このデータをモデル化するより良い方法はありますか
- もしそうなら、モデルの設計行列/式はどのようになるでしょう。最終的には、JAGSのようなmcmcパッケージでベイジアン推論を使用してモデル係数を推定したいので、2次元スプラインの記述方法を知りたいです。
私の例を再現するRコード:
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