data(FBC07.dat)
Y.1 <- FBC07.dat[1:100,"Y.1"]
Y.2 <- FBC07.dat[1:100,"Y.2"]
coords <- as.matrix(FBC07.dat[1:100,c("coord.X", "coord.Y")])
#############################
## Univariate models
#############################
##Fit some competing models.
##Full model with nugget (Psi), partial sill (K),
##and spatial decay (Phi).
K.prior <- prior(dist="IG", shape=2, scale=5)
Psi.prior <- prior(dist="IG", shape=2, scale=5)
phi.prior <- prior(dist="UNIF", a=0.06, b=3)
var.update.control <-
list("K"=list(starting=5, tuning=0.5, prior=K.prior),
"Psi"=list(starting=5, tuning=0.5, prior=Psi.prior),
"phi"=list(starting=0.1, tuning=0.5, prior=phi.prior)
)
beta.control <- list(update="GIBBS", prior=prior(dist="FLAT"))
run.control <- list("n.samples"=1000, "sp.effects"=TRUE)
Fit.m1 <- spGGT(formula=Y.2~1, run.control=run.control,
coords=coords, var.update.control=var.update.control,
beta.update.control=beta.control,
cov.model="exponential")
plot(Fit.m1$p.samples)
summary(Fit.m1$p.samples)
##First reduced model with no nugget just partial sill and decay.
var.update.control <-
list("K"=list(starting=5, tuning=0.5, prior=K.prior),
"phi"=list(starting=0.1, tuning=0.5, prior=phi.prior)
)
Fit.m2 <- spGGT(formula=Y.2~1, run.control=run.control,
coords=coords, var.update.control=var.update.control,
beta.update.control=beta.control,
cov.model="exponential")
plot(Fit.m2$p.samples)
##Second reduced model with no nugget just partial sill and fixed
##decay at the WRONG value, which forces the wrong estimate of K.
phi.prior <- prior(dist="FIXED")
var.update.control <-
list("K"=list(starting=5, tuning=0.5, prior=K.prior),
"phi"=list(starting=0.1, prior=phi.prior)
)
Fit.m3 <- spGGT(formula=Y.2~1, run.control=run.control,
coords=coords, var.update.control=var.update.control,
beta.update.control=beta.control,
cov.model="exponential")
plot(Fit.m3$p.samples)
##For this data, DIC cannot distinguish between the first two
##models but does show that the third model is clearly
##wrong. An empirical semivariogram is useful
##for recognizing that the full model is the correct choice
##over the second model.
print(spDiag(Fit.m1))
print(spDiag(Fit.m2))
print(spDiag(Fit.m3))
##Use akima or MBA to produce interpolated surfaces of
##estimated random spatial effects.
m1.surf <- mba.surf(cbind(coords, rowMeans(Fit.m1$sp.effects)),
no.X=100, no.Y=100, extend=TRUE)$xyz.est
image(m1.surf, xaxs="r", yaxs="r",
main="Y.2 random spatial effects")
points(coords, pch=19)
##Now the full model using the Matern spatial correlation function.
##Also, for fun, update the spatial decay parameters
##phi and nu in a separate MH block. This provides finer control
##on the parameters' acceptance rate, but takes a bit longer to
##run.
phi.prior <- prior(dist="UNIF", a=0.06, b=3)
nu.prior <- prior(dist="UNIF", a=0.01, b=2)
var.update.control <-
list("K"=list(starting=5, tuning=0.5, prior=K.prior),
"Psi"=list(starting=5, tuning=0.5, prior=Psi.prior),
"phi"=list(sample.order=1, starting=0.1,
tuning=0.5, prior=phi.prior),
"nu"=list(sample.order=1, starting=0.1,
tuning=0.5, prior=nu.prior)
)
run.control <- list("n.samples"=1000, "sp.effects"=FALSE)
Fit.m4 <-
spGGT(formula=Y.2~1, run.control=run.control,
coords=coords, var.update.control=var.update.control,
beta.update.control=beta.control,
cov.model="matern")
plot(Fit.m4$p.samples)
##Solve the Matern correlation function for the estimated
##95% CI for effective decay (e.g., distance at which the
##correlation drops to 0.05).
phi.hat <- quantile(Fit.m4$p.samples[,"Phi"], c(0.50,0.025,0.975))
nu.hat <- quantile(Fit.m4$p.samples[,"Nu"], c(0.50,0.025,0.975))
matern <- function(cor, eff.d, phi, nu){
cor - (eff.d*phi)^nu/(2^(nu-1)*gamma(nu))*besselK(x=eff.d*phi, nu=nu)
}
##50print(uniroot(matern, interval=c(1, 50),
cor=0.05, phi=phi.hat[1], nu=nu.hat[1])$root)
print(uniroot(matern, interval=c(1, 50),
cor=0.05, phi=phi.hat[2], nu=nu.hat[2])$root)
print(uniroot(matern, interval=c(1, 50),
cor=0.05, phi=phi.hat[3], nu=nu.hat[3])$root)
##Finally, the full model again but this time update the Beta
##using MH. Using the default of sample.order=0, this sampling
##scheme is simply a single block MH proposal of all model parameters.
##Also, the first run uses the default tuning value for the Beta
##(i.e., chol(vcov(lm(Y~X))). Both chains use a normal prior on Beta;
##however, the first chain allows for a vague prior, where as the
##second is much too strict.
var.update.control <-
list("K"=list(starting=5, tuning=0.5, prior=K.prior),
"Psi"=list(starting=5, tuning=0.5, prior=Psi.prior),
"phi"=list(starting=0.1, tuning=0.5, prior=phi.prior)
)
##Chain 1: vague prior normal variance of 1/0.001 = 1000
beta.prior <- prior(dist="NORMAL", mu=5, precision=0.001)
beta.control <- list(update="MH", prior=beta.prior)
Fit.m5.a <-
spGGT(formula=Y.2~1, run.control=run.control,
coords=coords, var.update.control=var.update.control,
beta.update.control=beta.control,
cov.model="exponential")
##Chain 2: restrictive prior normal variance of 1/5 = 0.2
##(i.e., crazy strict)
beta.prior <- prior(dist="NORMAL", mu=5, precision=5)
beta.control <- list(update="MH", prior=beta.prior, tuning=0.75)
Fit.m5.b <-
spGGT(formula=Y.2~1, run.control=run.control,
coords=coords, var.update.control=var.update.control,
beta.update.control=beta.control,
cov.model="exponential")
plot(mcmc.list(Fit.m5.a$p.samples, Fit.m5.b$p.samples))
##Now just for fun, here is the full model but using the weakly
##informative half-Cauchy for the nugget (Psi) and partial sill (K).
K.prior <- prior(dist="HC", a=50)
Psi.prior <- prior(dist="HC", a=50)
phi.prior <- prior(dist="UNIF", a=0.06, b=3)
var.update.control <-
list("K"=list(starting=5, tuning=0.5, prior=K.prior),
"Psi"=list(starting=5, sample.order=1, tuning=2, prior=Psi.prior),
"phi"=list(starting=0.1, sample.order=2, tuning=1, prior=phi.prior)
)
beta.control <- list(update="GIBBS", prior=prior(dist="FLAT"))
run.control <- list("n.samples"=3000, "sp.effects"=TRUE)
Fit.m1 <- spGGT(formula=Y.2~1, run.control=run.control,
coords=coords, var.update.control=var.update.control,
beta.update.control=beta.control,
cov.model="exponential")
plot(Fit.m1$p.samples)
summary(Fit.m1$p.samples)
#############################
## Multivariate models
#############################
##Full model with non-spatial cross-covariance
##(Psi) matrix, spatial cross-covariance matrix (K),
##and response specific spatial decay parameter (Phi)
##(i.e., a non-separable model).
##These chains really need to be run for several thousand
##samples (e.g., 10,000). Also note that it is much easier to maintain
##a healthy acceptance rate for each parameter if they
##are updated individually using the sample.order
##directive, as shown in the second example below.
K.prior <- prior(dist="IWISH", df=2, S=diag(c(3, 6)))
Psi.prior <- prior(dist="IWISH", df=2, S=diag(c(7, 5)))
phi.prior <- prior(dist="UNIF", a=0.06, b=3)
##The matrix starting values for K and Psi are actually
##passed as the sqrt of the desired starting values.
##This is only done if K or Psi are full cross-covariance
##matrices and serve to insure that the true starting value
##matrix is positive definite.
K.starting <- matrix(c(2,-3, 0, 1), 2, 2)
Psi.starting <- diag(c(3, 2))
var.update.control <-
list("K"=list(starting=K.starting, tuning=diag(c(0.08, 0.3, 0.08)),
prior=K.prior),
"Psi"=list(starting=Psi.starting, tuning=diag(c(0.08, 0.3, 0.08)),
prior=Psi.prior),
"phi"=list(starting=0.1, tuning=0.5,
prior=list(phi.prior, phi.prior))
)
beta.control <- list(update="GIBBS", prior=prior(dist="FLAT"))
run.control <- list("n.samples"=2000, "sp.effects"=FALSE)
Fit.mv.m1 <-
spGGT(formula=list(Y.1~1, Y.2~1), run.control=run.control,
coords=coords, var.update.control=var.update.control,
beta.update.control=beta.control,
cov.model="exponential")
plot(Fit.mv.m1$p.samples)
##Calculate the mean K correlation matrix. Note that since K is
##specified as a full cross-covariance matrix, the posterior
##samples are returned for the lower triangle of the symmetric K,
##in column major order.
K <- matrix(0, 2, 2)
K[lower.tri(K, diag=TRUE)] <-
colMeans(Fit.mv.m1$p.samples[,c("K_1","K_2","K_3")])
K[upper.tri(K, diag=FALSE)] <- t(K)[upper.tri(K, diag=FALSE)]
print(cov2cor(K))
##Now using sample order. Note this takes ~3 times as long
##to run, but provides much finer control of acceptance rates.
var.update.control <-
list("K"=list(sample.order=0, starting=K.starting,
tuning=diag(c(0.3, 0.5, 0.2)), prior=K.prior),
"Psi"=list(sample.order=1, starting=Psi.starting,
tuning=diag(c(0.2, 0.5, 0.2)), prior=Psi.prior),
"phi"=list(sample.order=2, starting=0.1,
tuning=0.5, prior=list(phi.prior, phi.prior))
)
run.control <- list("n.samples"=2000, "sp.effects"=TRUE)
Fit.mv.m2 <-
spGGT(formula=list(Y.1~1, Y.2~1), run.control=run.control,
coords=coords, var.update.control=var.update.control,
beta.update.control=beta.control,
cov.model="exponential")
plot(Fit.mv.m2$p.samples)
##Now again check out the random spatial effects. Recall,
##these are stored in the sp.effects matrix, which is organized
##as m consecutive rows for each point.
rand.effect.Y.1 <-
Fit.mv.m2$sp.effects[seq(1, nrow(Fit.mv.m2$sp.effects), 2),]
rand.effect.Y.2 <-
Fit.mv.m2$sp.effects[seq(2, nrow(Fit.mv.m2$sp.effects), 2),]
rand.effect.Y.1.surf <-
mba.surf(cbind(coords, rowMeans(rand.effect.Y.1)),
no.X=100, no.Y=100, extend=TRUE)$xyz.est
rand.effect.Y.2.surf <-
mba.surf(cbind(coords, rowMeans(rand.effect.Y.2)),
no.X=100, no.Y=100, extend=TRUE)$xyz.est
##The estimated negative value of off-diagonal element in K is
##clearly seen in the map of random spatial effects.
par(mfrow=c(1,2))
image(rand.effect.Y.1.surf, xaxs="r", yaxs="r",
main="Y.1 random spatial effects")
contour(rand.effect.Y.1.surf, add=TRUE)
image(rand.effect.Y.2.surf, xaxs="r", yaxs="r",
main="Y.2 random spatial effects")
contour(rand.effect.Y.2.surf, add=TRUE)
##Now a simpler model. Specifically, the full model shows that
##there is negligible non-spatial cross-covariance, therefore,
##Psi might just be modeled with a diagonal covariance matrix.
##This is actually the model which gave rise to this synthetic
##data set.
K.prior <- prior(dist="IWISH", df=2, S=diag(c(3, 6)))
Psi.prior <- prior(dist="IG", shape=2, scale=5)
phi.prior <- prior(dist="UNIF", a=0.06, b=3)
var.update.control <-
list("K"=list(sample.order=0, starting=K.starting,
tuning=diag(c(0.3, 0.5, 0.2)), prior=K.prior),
"Psi"=list(sample.order=1, starting=5,
tuning=0.5, prior=list(Psi.prior, Psi.prior)),
"phi"=list(sample.order=2, starting=0.1,
tuning=0.5, prior=list(phi.prior, phi.prior))
)
run.control <- list("n.samples"=2000)
Fit.mv.m3 <-
spGGT(formula=list(Y.1~1, Y.2~1), run.control=run.control,
coords=coords, var.update.control=var.update.control,
beta.update.control=beta.control,
cov.model="exponential")
plot(Fit.mv.m3$p.samples)
summary(Fit.mv.m3$p.samples)
##Finally, a really simple model which we know makes no sense
##for this data set. Specifically, a single variance parameter
##for the diagonal elements of K and Psi and common spatial decay,
##phi. Also, we use a spherical spatial covariance function, just
##because we can.
K.prior <- prior(dist="IG", shape=2, scale=5)
Psi.prior <- prior(dist="IG", shape=2, scale=5)
phi.prior <- prior(dist="UNIF", a=0.06, b=3)
var.update.control <-
list("K"=list(starting=5, tuning=0.5, prior=K.prior),
"Psi"=list(starting=5, tuning=0.5, prior=Psi.prior),
"phi"=list(starting=0.1, tuning=0.5, prior=phi.prior)
)
Fit.mv.m4 <-
spGGT(formula=list(Y.1~1, Y.2~1), run.control=run.control,
coords=coords, var.update.control=var.update.control,
beta.update.control=beta.control,
cov.model="spherical")
plot(Fit.mv.m4$p.samples)
Run the code above in your browser using DataLab