Below is code for a number of different models. The results of some but not all models are run below. You can do these on your own.
There is code for obtaining estimate of the posterior distribution of the icc (intra-class correlation), as well as the posterior probabilities for specific hypotheses. I also put in a better way to extract posterior values of parameter from samples (compared to what I did first time I did this).
The packages that we’ll use are
library(lme4)
library(lmerTest)
library(rjags)
library(runjags)
library(coda)
library(texreg)
Set working directory to where the data live and set up data for initial analyses:
setwd("D:/Dropbox/edps 590BAY/Lectures/8 Multilevel models")
ano.wide <- read.table("anorexia_wide.txt",header=TRUE)
ano.wide$change <- ano.wide$weight2 - ano.wide$weight1
(n <- nrow(ano.wide))
## [1] 72
head(ano.wide)
## Rx person weight1 weight2 change
## 1 1 1 80.5 82.2 1.7
## 2 1 2 84.9 85.6 0.7
## 3 1 3 81.5 81.4 -0.1
## 4 1 4 82.6 81.9 -0.7
## 5 1 5 79.9 76.4 -3.5
## 6 1 6 88.7 103.6 14.9
Let’s do some graphics to look at the data. First we’ll just look at histograms of before treatment, after treatment, and change. We’ll add a 2nd graph of change but looking at is a bit differently. For the 2nd graph of change we need to re-format the data, and create treatment dummy codes
ano <- read.table("anorexia_long.txt",header=TRUE)
ano <- ano[order(ano$girl),]
ano$Rx1 <- ifelse(ano$Rx==1,1,0)
ano$Rx2 <- ifelse(ano$Rx==2,1,0)
ano$Rx3 <- ifelse(ano$Rx==3,1,0)
and now for the graphs
par(mfrow=c(2,2))
hist(ano.wide$weight1, main='Weight Before Treatment',col="darkseagreen1")
hist(ano.wide$weight2, main='Weight After Treatment',col="darkseagreen1")
hist(ano.wide$change, main='Change in Weight',col="darkseagreen1")
plot(ano$time,ano$weight,
type="n",
ylim=c(65,104),
xlab="Before/After Treatment",
ylab="Weight in Pounds",
main="Change for Each Girl"
)
for (i in 1:n){
g <- subset(ano,ano$girl==i)
lines(g$time,g$weight,col=i,lwd=2)
}
This 4th plot show different intercepts and different slopes. To better see what’s going on, we’ll compute means for each treatment before and after treatment
# means for each treatment
byRx <- aggregate(ano$weight,list(ano$Rx),FUN="mean")
# mean for treatment x time
rx_by_time <- aggregate(ano$weight,list(ano$Rx,ano$time),FUN="mean")
names(rx_by_time) <-c("rx","time","weight")
rx1 <- subset(rx_by_time,rx==1) # Cognitive
rx2 <- subset(rx_by_time,rx==2) # Control
rx3 <- subset(rx_by_time,rx==3) # Family
Now to look at these…what do you expect based on this?
par(mfrow=c(1,1))
plot(rx2$time,rx2$weight,
type='b',
col="cyan",
main="Weight Change by Treatment",
ylim=c(80,95),
xlim=c(1,2),
xlab="When Weight Measured",
ylab="Weight",
xaxt="n"
)
axis(1, at = seq(1,2,by=1),labels=c("Before","After"))
lines(rx1$time,rx1$weight,type="b",col="blue")
lines(rx3$time,rx3$weight,type="b",col="red")
legend(1.02,95,title="Treatment",legend=c("Control", "Cognitive", "Family"), col=c("cyan","blue","red"),lty=c(1,1,1),cex=0.8)
If we are taking a Bayesian approach, we would not look at MLE; however, for pedagogical purposes, we do it here. Before using Bayesian estimation, we’ll see what restricted maximum likelihood (REML) yields. I choose REML since these are unbiased; however, if we’re only looking at lmer models from package lme4, I would normally choose MLE. Using the lme4 package.
########################################################
# Simple Model using lme4 --- just a random intercept #
########################################################
# Remember: treatment = 1 Cognitive
# = 2 Control
# = 3 Family
summary(model1reml <- lmer(weight ~ time + (1 | girl), data=ano, REML=TRUE))
Here are the fitted values from model 0
girl <- data.frame(seq(1:n))
par(mfrow=c(1,1))
b1 <- data.frame(coef(model1reml)[[1]])
tmp1 <- cbind(b1,girl)
names(tmp1) <- c("b0","b1","girl")
ano <- merge(ano,tmp1,by="girl")
ano$y.1 <- ano$b0 + ano$b1*ano$time
y <- subset(ano,ano$girl==1)
plot(y$time,y$y.1,
type="n",
ylim=c(65,104),
xlab="Before/After Treatment",
ylab="Weight in Pounds",
main="weight ~ time + (1 | girl)",
xaxt="n"
)
axis(1, at = seq(1,2,by=1),labels=c("Before","After"))
for (i in 1:n){
g <- subset(ano,ano$girl==i)
lines(g$time, g$y.1, col=i)
}
Now make the model a bit more complex by adding in treatment
########################################################
#
# Model 2: weight ~ time + treatment + (1 | girl) #
########################################################
ano$treatment <- as.factor(ano$Rx)
model2reml <- lmer(weight ~ time + treatment + (1 | girl), data=ano, REML=TRUE)
summary(model2reml)
Now graphing conditional values
b2 <- data.frame(coef(model2reml)[[1]])
tmp2 <- cbind(b2,girl)
names(tmp2) <- c("b0.2","b1.2","b2.2","b3.2","girl")
ano <- merge(ano,tmp2,by="girl")
ano$y.2 <- ano$b0.2 + ano$b1.2*ano$time + ano$b2.2*ano$Rx2 + ano$b3.2*ano$Rx3
y <- subset(ano,ano$girl==1)
plot(y$time,y$y.2,
type="n",
ylim=c(65,104),
xlab="Before/After Treatment",
ylab="Weight in Pounds",
main="weight ~ time + treatment + (1 | girl)",
xaxt="n"
)
axis(1, at = seq(1,2,by=1),labels=c("Before","After"))
for (i in 1:n){
g <- subset(ano,ano$girl==i)
lines(g$time, g$y.2, col=i)
}
Doesn’t look much different, so let’s add an interaction between time and treatment. We see this is in the data.
#######################################################
# Model 3: weight ~ time + treatment + time*treatment + ( 1 | girl)
#
########################################################
model3reml <- lmer(weight ~ time + treatment + time*treatment + ( 1 | girl),data=ano,REML=TRUE)
summary(model3reml)
The fitted values are
b3 <- data.frame(coef(model3reml)[[1]])
tmp3 <- cbind(b3,girl)
names(tmp3) <- c("b0.3","b1.3","b2.3","b3.3","b4.3","b5.3","girl")
ano <- merge(ano,tmp3,by="girl")
ano$y.3 <- ano$b0.3 + ano$b1.3*ano$time + ano$b2.3*ano$Rx2 + ano$b3.3*ano$Rx3 + ano$b4.3*ano$time*ano$Rx2 + ano$b5.3*ano$time*ano$Rx3
y <- subset(ano,ano$girl==1)
plot(y$time,y$y.3,
type="n",
ylim=c(65,104),
xlab="Before/After Treatment",
ylab="Weight in Pounds",
main="~time+treatment+time*treatment+( 1 | girl)",
xaxt="n"
)
axis(1, at = seq(1,2,by=1),labels=c("Before","After"))
for (i in 1:n){
g <- subset(ano,ano$girl==i)
lines(g$time, g$y.3, col=i)
}
Based on our initial look at the data, we might want a random slope but NO random intercept.
########################################################
# Model 4: weight ~ time + treatment + time*treatment + ( 0 +time|girl)
########################################################
model4reml <- lmer(weight ~ time + treatment + time*treatment + ( 1 | girl) + ( 0 + time |girl),data=ano,REML=TRUE)
## boundary (singular) fit: see ?isSingular
model4reml <- lmer(weight ~ time + treatment + time*treatment + ( 0 + time |girl),data=ano,REML=TRUE)
summary(model4reml)
What are fitted values now? These “look” like the data.
b4 <- data.frame(coef(model4reml)[[1]])
tmp4 <- cbind(b4,girl)
names(tmp4) <- c("b0.4","b1.4","b2.4","b3.4","b4.4","b5.4","girl")
ano <- merge(ano,tmp4,by="girl")
ano$y.4 <- ano$b0.4 + ano$b1.4*ano$time + ano$b2.4*ano$Rx2 + ano$b3.4*ano$Rx3 + ano$b4.4*ano$time*ano$Rx2 + ano$b5.4*ano$time*ano$Rx3
plot(ano$time,ano$y.4,
type="n",
ylim=c(65,104),
xlab="Before/After Treatment",
ylab="Weight in Pounds",
main="~ ... +time*treatment+(0+time|girl)",
xaxt="n"
)
axis(1, at = seq(1,2,by=1),labels=c("Before","After"))
for (i in 1:n){
g <- subset(ano,ano$girl==i)
lines(g$time, g$y.4, col=i)
}
## Summary of model fit via MLE
screenreg(c(model1reml, model2reml, model3reml, model4reml))
##
## =========================================================================
## Model 1 Model 2 Model 3 Model 4
## -------------------------------------------------------------------------
## (Intercept) 79.64 *** 80.05 *** 79.68 *** 79.68 ***
## (1.55) (1.70) (2.30) (1.99)
## time 2.76 ** 2.76 ** 3.01 * 3.01 *
## (0.94) (0.94) (1.40) (1.35)
## treatment2 -2.86 * 2.32 2.32
## (1.38) (3.35) (2.89)
## treatment3 2.67 -3.72 -3.72
## (1.56) (3.78) (3.27)
## time:treatment2 -3.46 -3.46
## (2.03) (1.96)
## time:treatment3 4.26 4.26
## (2.30) (2.22)
## -------------------------------------------------------------------------
## AIC 955.48 942.76 929.86 922.05
## BIC 967.35 960.58 953.61 945.81
## Log Likelihood -473.74 -465.38 -456.93 -453.02
## Num. obs. 144 144 144 144
## Num. groups: girl 72 72 72 72
## Var: girl (Intercept) 13.84 10.04 11.80
## Var: Residual 31.87 31.87 28.34 22.91
## Var: girl time 6.89
## =========================================================================
## *** p < 0.001; ** p < 0.01; * p < 0.05
To illustrate how to fit models, we start simple and work to more complex.
This model is also called the Null HLM and is the same as random effects ANOVA.
########################################################
# Bayesian Model 0 : random intercept no predictors (null hlm)
########################################################
dataList <- list(
y = ano$weight, # sd of weight (response)
sdY = sd(ano$weight), # sd of response
n = length(ano$weight), # number obs
ng= length(ano$weight)/2, # number of girls
girl= ano$girl
)
The model part
model0 <- "model {
for (i in 1:n) { # likelihood
y[i] ~ dnorm(mu[i],precision)
mu[i] <- U0j[girl[i]] # note index
}
for (j in 1:ng) { # random intercepts
U0j[j] ~ dnorm(g0,ptau)
}
g0 ~ dnorm(0,1/(100*sdY^2)) # other priors, mean of random
tau ~ dunif(0.0001,200) # sd of random
ptau <- 1/tau^2 # precision random
sigma ~ dunif(0.0001,2000) # sd of response (weight)
precision <- 1/sigma^2 # precision of weight/response
total.var <- sigma^2 + tau^2
icc <- tau^2/total.var
}"
writeLines(model0, con="model0.txt")
I used different random number generators to show you what is available. This shouldn’t make a difference in results.
start1 = list("g0"=mean(ano$weight), "sigma"=sd(ano$weight), "tau"=.5, .RNG.name="base::Wichmann-Hill", .RNG.seed=523)
start2 = list("g0"=rnorm(1,0,3), "sigma"=5, "tau"=1, .RNG.name="base::Marsaglia-Multicarry", .RNG.seed=57)
start3 = list("g0"=rnorm(1,3,4), "sigma"=10, "tau"=5, .RNG.name="base::Super-Duper", .RNG.seed=24)
start4 = list("g0"=rnorm(1,-3,10), "sigma"=50, "tau"=20, .RNG.name="base::Mersenne-Twister", .RNG.seed=72100)
start <- list(start1,start2,start3,start4)
And run jags
model0.runjags <- run.jags(model=model0,
method="parallel",
monitor=c("g0", "sigma", "tau","total.var", "icc"),
data=dataList,
n.chains=4,
sample=50000,
burnin=5000,
inits=start,
thin=15)
## Calling 4 simulations using the parallel method...
## Following the progress of chain 1 (the program will wait for all chains
## to finish before continuing):
## Welcome to JAGS 4.3.0 on Fri Oct 14 10:55:34 2022
## JAGS is free software and comes with ABSOLUTELY NO WARRANTY
## Loading module: basemod: ok
## Loading module: bugs: ok
## . . Reading data file data.txt
## . Compiling model graph
## Resolving undeclared variables
## Allocating nodes
## Graph information:
## Observed stochastic nodes: 144
## Unobserved stochastic nodes: 75
## Total graph size: 382
## . Reading parameter file inits1.txt
## . Initializing model
## . Adapting 1000
## -------------------------------------------------| 1000
## ++++++++++++++++++++++++++++++++++++++++++++++++++ 100%
## Adaptation successful
## . Updating 5000
## -------------------------------------------------| 5000
## ************************************************** 100%
## . . . . . . Updating 750000
## -------------------------------------------------| 750000
## ************************************************** 100%
## . . . . Updating 0
## . Deleting model
## .
## All chains have finished
## Simulation complete. Reading coda files...
## Coda files loaded successfully
## Calculating summary statistics...
## Calculating the Gelman-Rubin statistic for 5 variables....
## Finished running the simulation
plot(model0.runjags)
## Generating plots...
print(model0.runjags)
##
## JAGS model summary statistics from 200000 samples (thin = 15; chains = 4; adapt+burnin = 6000):
##
## Lower95 Median Upper95 Mean SD Mode MCerr MC%ofSD
## g0 82.529 83.787 85.081 83.785 0.64938 -- 0.0033175 0.5
## sigma 5.117 6.0904 7.1781 6.1253 0.53426 -- 0.0032203 0.6
## tau 0.74594 3.3152 5.0795 3.193 1.0639 -- 0.0087614 0.8
## total.var 37.551 48.616 61.401 49.132 6.1899 -- 0.031094 0.5
## icc 3.786e-07 0.2302 0.41532 0.22729 0.1157 -- 0.00082215 0.7
##
## SSeff AC.150 psrf
## g0 38316 0.0067444 1.0001
## sigma 27524 0.053373 0.99999
## tau 14745 0.16135 1.0001
## total.var 39628 0.0030098 0.99999
## icc 19806 0.095698 1.0001
##
## Total time taken: 1.7 minutes
summary(model1reml)
## Linear mixed model fit by REML. t-tests use Satterthwaite's method [
## lmerModLmerTest]
## Formula: weight ~ time + (1 | girl)
## Data: ano
##
## REML criterion at convergence: 947.5
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -1.92295 -0.46924 -0.03478 0.52092 2.24652
##
## Random effects:
## Groups Name Variance Std.Dev.
## girl (Intercept) 13.84 3.720
## Residual 31.87 5.645
## Number of obs: 144, groups: girl, 72
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 79.6444 1.5509 99.2652 51.353 < 2e-16 ***
## time 2.7639 0.9409 71.0000 2.938 0.00446 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr)
## time -0.910
There are multiple ways that we can do this: (1) within jags (see above), (2) monte carlo after obtaining posteriors, (3) multiple posteriors which is illustrated below.
samps <-combine.mcmc(mcmc.objects = model0.runjags$mcmc)
# I need to know which columns I need
colnames(samps)
## [1] "g0" "sigma" "tau" "total.var" "icc"
sigma2 <- samps[,2]**2
tau2 <- samps[,3]**2
icc <- tau2/(sigma2+tau2)
summary(icc)
##
## Iterations = 6001:3005986
## Thinning interval = 15
## Number of chains = 1
## Sample size per chain = 2e+05
##
## 1. Empirical mean and standard deviation for each variable,
## plus standard error of the mean:
##
## Mean SD Naive SE Time-series SE
## 0.2264698 0.1154773 0.0002582 0.0006845
##
## 2. Quantiles for each variable:
##
## 2.5% 25% 50% 75% 97.5%
## 0.008047 0.143948 0.228794 0.308976 0.446422
Now for our next model where we add in a predictor, “time”:
####################################################################
# Bayesian Model 1 : random intercept and fixed time #
####################################################################
dataList <- list(
y = ano$weight,
time = ano$time,
sdY = sd(ano$weight),
n = length(ano$weight),
ng= length(ano$weight)/2,
girl= ano$girl
)
model1 <- "model {
for (i in 1:n) {
y[i] ~ dnorm(mu[i],precision)
mu[i] <- b0j[girl[i]] + g1*time[i]
}
for (j in 1:ng) {
b0j[j] ~ dnorm(g0,ptau)
}
g0 ~ dnorm(0,1/(100*sdY^2))
g1 ~ dnorm(0,1/(100*sdY^2))
tau ~ dunif(0.0001,200)
ptau <- 1/tau^2
sigma ~ dunif(0.0001,2000)
precision <- 1/sigma^2
}"
writeLines(model1, con="model1.txt")
start1 = list("g0"=mean(ano$weight),"g1"=rnorm(1,0,3), "sigma"=sd(ano$weight), "tau"=.5,
.RNG.name="base::Wichmann-Hill", .RNG.seed=523)
start2 = list("g0"=rnorm(1,0,3), "g1"=rnorm(1,0,3), "sigma"=5, "tau"=1,
.RNG.name="base::Marsaglia-Multicarry", .RNG.seed=57)
start3 = list("g0"=rnorm(1,3,4), "g1"=rnorm(1,3,4), "sigma"=50, "tau"=3,
.RNG.name="base::Super-Duper", .RNG.seed=24)
start4 = list("g0"=rnorm(1,-3,10), "g1"=rnorm(1,-3,10), "sigma"=10, "tau"=10,
.RNG.name="base::Mersenne-Twister", .RNG.seed=72100)
start <- list(start1,start2,start3,start4)
start <- list(start1,start2,start3,start4)
model1.runjags <- run.jags(model=model1,
method="parallel",
monitor=c("g0", "g1", "sigma", "tau"),
data=dataList,
sample=20000,
n.chains=4,
thin=10,
inits=start)
## Calling 4 simulations using the parallel method...
## Following the progress of chain 1 (the program will wait for all chains
## to finish before continuing):
## Welcome to JAGS 4.3.0 on Fri Oct 14 10:57:25 2022
## JAGS is free software and comes with ABSOLUTELY NO WARRANTY
## Loading module: basemod: ok
## Loading module: bugs: ok
## . . Reading data file data.txt
## . Compiling model graph
## Resolving undeclared variables
## Allocating nodes
## Graph information:
## Observed stochastic nodes: 144
## Unobserved stochastic nodes: 76
## Total graph size: 671
## . Reading parameter file inits1.txt
## . Initializing model
## . Adapting 1000
## -------------------------------------------------| 1000
## ++++++++++++++++++++++++++++++++++++++++++++++++++ 100%
## Adaptation successful
## . Updating 4000
## -------------------------------------------------| 4000
## ************************************************** 100%
## . . . . . Updating 200000
## -------------------------------------------------| 200000
## ************************************************** 100%
## . . . . Updating 0
## . Deleting model
## .
## All chains have finished
## Simulation complete. Reading coda files...
## Coda files loaded successfully
## Calculating summary statistics...
## Calculating the Gelman-Rubin statistic for 4 variables....
## Finished running the simulation
# And checking a bit more whether model1.runjags converged
plot(model1.runjags)
## Generating plots...
print(model1.runjags)
##
## JAGS model summary statistics from 80000 samples (thin = 10; chains = 4; adapt+burnin = 5000):
##
## Lower95 Median Upper95 Mean SD Mode MCerr MC%ofSD SSeff
## g0 76.53 79.613 82.764 79.606 1.589 -- 0.012911 0.8 15147
## g1 0.85913 2.7778 4.6803 2.7836 0.97037 -- 0.007939 0.8 14940
## sigma 4.8576 5.7862 6.8531 5.8217 0.51778 -- 0.0038384 0.7 18197
## tau 1.5737 3.5984 5.381 3.5214 0.94995 -- 0.010339 1.1 8441
##
## AC.100 psrf
## g0 0.027198 1.0001
## g1 0.029574 1.0002
## sigma 0.050738 1.0004
## tau 0.14458 1.0012
##
## Total time taken: 38.5 seconds
# For comparison
summary(model1reml)
## Linear mixed model fit by REML. t-tests use Satterthwaite's method [
## lmerModLmerTest]
## Formula: weight ~ time + (1 | girl)
## Data: ano
##
## REML criterion at convergence: 947.5
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -1.92295 -0.46924 -0.03478 0.52092 2.24652
##
## Random effects:
## Groups Name Variance Std.Dev.
## girl (Intercept) 13.84 3.720
## Residual 31.87 5.645
## Number of obs: 144, groups: girl, 72
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 79.6444 1.5509 99.2652 51.353 < 2e-16 ***
## time 2.7639 0.9409 71.0000 2.938 0.00446 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr)
## time -0.910
After fitting model, I decided I want an ICC, so…
# Compute residual ICC (intra-class correlation) and credible interval
samps <-combine.mcmc(mcmc.objects = model1.runjags$mcmc)
colnames(samps)
## [1] "g0" "g1" "sigma" "tau"
sigma2 <- samps[,3]**2
tau2 <- samps[,4]**2
icc1 <- tau2/(sigma2+tau2)
summary(icc1)
##
## Iterations = 5001:804991
## Thinning interval = 10
## Number of chains = 1
## Sample size per chain = 80000
##
## 1. Empirical mean and standard deviation for each variable,
## plus standard error of the mean:
##
## Mean SD Naive SE Time-series SE
## 0.2764488 0.1151774 0.0004072 0.0011031
##
## 2. Quantiles for each variable:
##
## 2.5% 25% 50% 75% 97.5%
## 0.03616 0.19857 0.28118 0.35806 0.49009
This model is too simple for the data, so we’ll go on to our next model, model2 which adds treatment as a fixed effect.
##################################################################
# Bayesian Model 2 : random intercept + fixed time + Rx #
##################################################################
dataList <- list(
y = ano$weight,
time = ano$time,
rx1 = ano$Rx1,
rx3 = ano$Rx3,
sdY = sd(ano$weight),
n = length(ano$weight),
ng= length(ano$weight)/2,
girl= ano$girl
)
model2 <- "model {
for (i in 1:n) {
y[i] ~ dnorm(mu[i],precision)
mu[i] <- b0j[girl[i]] + g1*time[i] + g2*rx1[i] + g3*rx3[i]
}
for (j in 1:ng) {
b0j[j] ~ dnorm(g0,ptau)
}
g0 ~ dnorm(0,1/(100*sdY^2))
g1 ~ dnorm(0,1/(100*sdY^2))
g2 ~ dnorm(0,1/(100*sdY^2))
g3 ~ dnorm(0,1/(100*sdY^2))
tau ~ dunif(0.0001,200)
ptau <- 1/tau^2
sigma ~ dunif(0.0001,2000)
precision <- 1/sigma^2
}"
writeLines(model2, con="model2.txt")
start1 = list("g0"=mean(ano$weight),"g1"=rnorm(1,0,3), "g2"=rnorm(1,0,3),"g3"=rnorm(1,0,3),
"sigma"=sd(ano$weight), "tau"=.5, .RNG.name="base::Wichmann-Hill", .RNG.seed=523)
start2 = list("g0"=rnorm(1,0,3), "g1"=rnorm(1,0,3), "g2"=rnorm(1,-1,3), "g3"=rnorm(1,0,3),
"sigma"=5, "tau"=1, .RNG.name="base::Marsaglia-Multicarry", .RNG.seed=57)
start3 = list("g0"=rnorm(1,3,4), "g1"=rnorm(1,3,4), "g2"=rnorm(1,3,4), "g3"=rnorm(1,0,3),
"sigma"=50, "tau"=3, .RNG.name="base::Super-Duper", .RNG.seed=24)
start4 = list("g0"=rnorm(1,-3,10), "g1"=rnorm(1,-3,10), "g2"=rnorm(1,10,5), "g3"=rnorm(1,0,3),
"sigma"=10, "tau"=10, .RNG.name="base::Mersenne-Twister", .RNG.seed=72100)
start <- list(start1,start2,start3,start4)
model2.runjags <- run.jags(model=model2,
method="parallel",
monitor=c("g0", "g1", "g2","g3","sigma", "tau"),
data=dataList,
sample=20000,
n.chains=4,
thin=10,
inits=start)
## Calling 4 simulations using the parallel method...
## Following the progress of chain 1 (the program will wait for all chains
## to finish before continuing):
## Welcome to JAGS 4.3.0 on Fri Oct 14 10:58:10 2022
## JAGS is free software and comes with ABSOLUTELY NO WARRANTY
## Loading module: basemod: ok
## Loading module: bugs: ok
## . . Reading data file data.txt
## . Compiling model graph
## Resolving undeclared variables
## Allocating nodes
## Graph information:
## Observed stochastic nodes: 144
## Unobserved stochastic nodes: 78
## Total graph size: 965
## . Reading parameter file inits1.txt
## . Initializing model
## . Adapting 1000
## -------------------------------------------------| 1000
## ++++++++++++++++++++++++++++++++++++++++++++++++++ 100%
## Adaptation successful
## . Updating 4000
## -------------------------------------------------| 4000
## ************************************************** 100%
## . . . . . . . Updating 200000
## -------------------------------------------------| 200000
## ************************************************** 100%
## . . . . Updating 0
## . Deleting model
## .
## All chains have finished
## Simulation complete. Reading coda files...
## Coda files loaded successfully
## Calculating summary statistics...
## Calculating the Gelman-Rubin statistic for 6 variables....
## Finished running the simulation
# And we should do some more model checking...
plot(model2.runjags)
## Generating plots...
print(model2.runjags)
##
## JAGS model summary statistics from 80000 samples (thin = 10; chains = 4; adapt+burnin = 5000):
##
## Lower95 Median Upper95 Mean SD Mode MCerr MC%ofSD SSeff
## g0 73.755 77.122 80.688 77.117 1.7592 -- 0.018509 1.1 9033
## g1 0.89853 2.7946 4.7061 2.794 0.97031 -- 0.0095332 1 10360
## g2 0.17535 2.8963 5.6152 2.8894 1.3849 -- 0.008085 0.6 29339
## g3 2.4247 5.5586 8.7142 5.56 1.6013 -- 0.0092449 0.6 30000
## sigma 4.913 5.8095 6.8547 5.8355 0.50442 -- 0.0044172 0.9 13041
## tau 0.53586 2.9675 4.6853 2.8494 1.0304 -- 0.014391 1.4 5127
##
## AC.100 psrf
## g0 0.11538 1.0001
## g1 0.093218 1.0001
## g2 0.017826 1
## g3 0.017716 1
## sigma 0.075106 1.0001
## tau 0.24454 1.0006
##
## Total time taken: 34.4 seconds
# For comparison
summary(model2reml)
## Linear mixed model fit by REML. t-tests use Satterthwaite's method [
## lmerModLmerTest]
## Formula: weight ~ time + treatment + (1 | girl)
## Data: ano
##
## REML criterion at convergence: 930.8
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.0131 -0.5380 -0.0562 0.6090 2.3744
##
## Random effects:
## Groups Name Variance Std.Dev.
## girl (Intercept) 10.04 3.168
## Residual 31.87 5.645
## Number of obs: 144, groups: girl, 72
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 80.0473 1.6992 123.5077 47.108 < 2e-16 ***
## time 2.7639 0.9409 71.0000 2.938 0.00446 **
## treatment2 -2.8604 1.3764 69.0000 -2.078 0.04141 *
## treatment3 2.6687 1.5567 69.0000 1.714 0.09096 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) time trtmn2
## time -0.831
## treatment2 -0.383 0.000
## treatment3 -0.339 0.000 0.418
samps <-combine.mcmc(mcmc.objects = model2.runjags$mcmc)
colnames(samps) # to see which columns I need
## [1] "g0" "g1" "g2" "g3" "sigma" "tau"
sigma2 <- samps[,5]**2
tau2 <- samps[,6]**2
icc2 <- tau2/(sigma2+tau2)
summary(icc2)
##
## Iterations = 5001:804991
## Thinning interval = 10
## Number of chains = 1
## Sample size per chain = 80000
##
## 1. Empirical mean and standard deviation for each variable,
## plus standard error of the mean:
##
## Mean SD Naive SE Time-series SE
## 0.2080618 0.1153097 0.0004077 0.0013918
##
## 2. Quantiles for each variable:
##
## 2.5% 25% 50% 75% 97.5%
## 0.004971 0.121053 0.208733 0.290632 0.432762
g2 <- samps[,3]
g3 <- samps[,4]
diff <- g3-g2
summary(diff)
##
## Iterations = 5001:804991
## Thinning interval = 10
## Number of chains = 1
## Sample size per chain = 80000
##
## 1. Empirical mean and standard deviation for each variable,
## plus standard error of the mean:
##
## Mean SD Naive SE Time-series SE
## 2.671969 1.566567 0.005539 0.005528
##
## 2. Quantiles for each variable:
##
## 2.5% 25% 50% 75% 97.5%
## -0.3917 1.6203 2.6740 3.7198 5.7564
hist(diff, main="Posterior of Differences between family & cognitive", col="cyan")
### What is the probability that family is better than cognitive?
prob <- mean(diff>0)
These results should not be treated as final, because we have more models to fit. However, this does illustrate how to be get postiors samples, compute variaous posteriors, get probabilities for hypothses, etc.
Next model (this will run fine but it is not run here)
##################################################################################
# Bayesian Model 3 : random intercept + fixed time + Rx + time*Rx #
##################################################################################
dataList <- list(
y = ano$weight,
time = ano$time,
rx1 = ano$Rx1,
rx3 = ano$Rx3,
sdY = sd(ano$weight),
n = length(ano$weight),
ng= length(ano$weight)/2,
girl= ano$girl
)
model3 <- "model {
for (i in 1:n) {
y[i] ~ dnorm(mu[i],precision)
mu[i] <- b0j[girl[i]] + g1*time[i] + g2*rx1[i] + g3*rx3[i] + g4*time[i]*rx1[i] + g5*time[i]*rx3[i]
}
for (j in 1:ng) {
b0j[j] ~ dnorm(g0,ptau)
}
g0 ~ dnorm(0,1/(100*sdY^2))
g1 ~ dnorm(0,1/(100*sdY^2))
g2 ~ dnorm(0,1/(100*sdY^2))
g3 ~ dnorm(0,1/(100*sdY^2))
g4 ~ dnorm(0,1/(100*sdY^2))
g5 ~ dnorm(0,1/(100*sdY^2))
tau ~ dunif(0.0001,200)
ptau <- 1/tau^2
sigma ~ dunif(0.0001,2000)
precision <- 1/sigma^2
}"
writeLines(model3, con="model3.txt")
start1 = list("g0"=mean(ano$weight),"g1"=rnorm(1,0,3), "g2"=rnorm(1,0,3),"g3"=rnorm(1,0,3),
"g4"=rnorm(1,0,3),"g5"=rnorm(1,0,3), "sigma"=sd(ano$weight), "tau"=.5,
.RNG.name="base::Wichmann-Hill", .RNG.seed=523)
start2 = list("g0"=rnorm(1,0,3), "g1"=rnorm(1,0,3), "g2"=rnorm(1,-1,3), "g3"=rnorm(1,0,3),
"g4"=rnorm(1,-1,3), "g5"=rnorm(1,0,3), "sigma"=5, "tau"=1,
.RNG.name="base::Marsaglia-Multicarry", .RNG.seed=57)
start3 = list("g0"=rnorm(1,3,4), "g1"=rnorm(1,3,4), "g2"=rnorm(1,3,4), "g3"=rnorm(1,0,3),
"g4"=rnorm(1,3,4), "g5"=rnorm(1,0,3), "sigma"=50, "tau"=5,
.RNG.name="base::Super-Duper", .RNG.seed=24)
start4 = list("g0"=rnorm(1,-3,10),"g1"=rnorm(1,-3,10), "g2"=rnorm(1,10,5), "g3"=rnorm(1,0,3),
"g4"=rnorm(1,2,5),
"g5"=rnorm(1,3,3), "sigma"=10, "tau"=10,
.RNG.name="base::Mersenne-Twister", .RNG.seed=72100)
start <- list(start1,start2,start3,start4)
model3.runjags <- run.jags(model=model3,
method="parallel",
monitor=c("g0","g1","g2","g3","g4","g5","sigma","tau"),
data=dataList,
sample=20000,
n.chains=4,
thin=20,
inits=start)
print(model3.runjags)
summary(model3.reml)
plot(model3.runjags)
samps <-combine.mcmc(mcmc.objects = model3.runjags$mcmc)
colnames(samps) # to see which columns I need
sigma2 <- samps[,7]**2
tau2 <- samps[,8]**2
icc3 <- tau2/(sigma2+tau2)
summary(icc3)
Now we’ll switch to random slope and drop the random intercept. This might be OK. This code will run but not run here.
##################################################################################
# Bayesian Model 4 : random slope + fixed time + Rx + time*Rx #
##################################################################################
dataList <- list(
y = ano$weight,
time = ano$time,
rx1 = ano$Rx1,
rx3 = ano$Rx3,
sdY = sd(ano$weight),
n = length(ano$weight),
ng= length(ano$weight)/2,
girl= ano$girl
)
model4 <- "model {
for (i in 1:n) {
y[i] ~ dnorm(mu[i],precision)
mu[i] <- g0 + g1*time[i] + b1j[girl[i]]*time[i] + g2*rx1[i] + g3*rx3[i]
+ g4*time[i]*rx1[i] + g5*time[i]*rx3[i]
}
for (j in 1:ng) {
b1j[j] ~ dnorm(0,ptau)
}
g0 ~ dnorm(0,1/(100*sdY^2))
g1 ~ dnorm(0,1/(100*sdY^2))
g2 ~ dnorm(0,1/(100*sdY^2))
g3 ~ dnorm(0,1/(100*sdY^2))
g4 ~ dnorm(0,1/(100*sdY^2))
g5 ~ dnorm(0,1/(100*sdY^2))
tau ~ dunif(0.0001,200)
ptau <- 1/tau^2
sigma ~ dunif(0.0001,2000)
precision <- 1/sigma^2
}"
writeLines(model4, con="model4.txt")
start1 = list("g0"=mean(ano$weight), "g1"=rnorm(1,1,3), "g2"=rnorm(1,0,3),"g3"=rnorm(1,0,3),
"g4"=rnorm(1,0,3), "g5"=rnorm(1,0,3), "sigma"=sd(ano$weight), "tau"=.5,
.RNG.name="base::Wichmann-Hill", .RNG.seed=523)
start2 = list("g0"=rnorm(1,0,3), "g1"=rnorm(1,-2,3), "g2"=rnorm(1,-1,3), "g3"=rnorm(1,0,3),
"g4"=rnorm(1,-1,3),"g5"=rnorm(1,0,3), "sigma"=5, "tau"=1,
.RNG.name="base::Marsaglia-Multicarry", .RNG.seed=57)
start3 = list("g0"=rnorm(1,3,4), "g1"=rnorm(1,0,3), "g2"=rnorm(1,3,4), "g3"=rnorm(1,0,3),
"g4"=rnorm(1,3,4), "g5"=rnorm(1,0,3), "sigma"=50, "tau"=5,
.RNG.name="base::Super-Duper", .RNG.seed=24)
start4 = list("g0"=rnorm(1,-3,10), "g1"=rnorm(1,5,3),"g2"=rnorm(1,10,5), "g3"=rnorm(1,0,3),
"g4"=rnorm(1,2,5), "g5"=rnorm(1,3,3), "sigma"=10, "tau"=10,
.RNG.name="base::Mersenne-Twister", .RNG.seed=72100)
start <- list(start1,start2,start3,start4)
model4.runjags <- run.jags(model=model4,
method="parallel",
monitor=c("g0","g1","g2","g3","g4","g5", "sigma", "tau"),
data=dataList,
sample=20000,
n.chains=4,
thin=5,
inits=start)
plot(model4.runjags)
print(model4.runjags)
summary(model4reml)
We’ll try a random intercept and slope. With only 2 time points, you can’t fit both random intercept and slope as well as correlation between the random intercept and slope. In this example, \[\tau_01=0\]. This seems to be just enough to get the model to fit. Let’s see what happens when you try to get estimate both.
##################################################################################
# Bayesian Model 5: random intercept & slope + fixed time + Rx1 + Rx3 #
# density of tau_0 doesn't look good #
##################################################################################
dataList <- list(
y = ano$weight,
time = ano$time,
rx1 = ano$Rx1,
rx3 = ano$Rx3,
sdY = sd(ano$weight),
n = length(ano$weight),
ng= length(ano$weight)/2,
girl= ano$girl
)
model5 <- "model {
for (i in 1:n) {
y[i] ~ dnorm(mu[i],precision)
mu[i] <- g0 + g1*time[i] + g2*rx1[i] + g3*rx3[i] + U0j[girl[i]] + U1j[girl[i]]*time[i]
}
for (j in 1:ng) {
U0j[j] ~ dnorm(0,ptau0)
U1j[j] ~ dnorm(0,ptau1)
}
g0 ~ dnorm(0,1/(100*sdY^2))
g1 ~ dnorm(0,1/(100*sdY^2))
g2 ~ dnorm(0,1/(100*sdY^2))
g3 ~ dnorm(0,1/(100*sdY^2))
ptau0 ~ dgamma(0.001,0.001)
tau0 <- 1/sqrt(ptau0)
tau1 ~ dunif(0.0001,200)
ptau1 <- 1/tau1^2
sigma ~ dunif(0.0001,2000)
precision <- 1/sigma^2
}"
writeLines(model5, con="model5.txt")
start1 = list("g0"=mean(ano$weight), "g1"=rnorm(1,1,3), "g2"=rnorm(1,1,3), "g3"=rnorm(1,4,3), "sigma"=sd(ano$weight), "ptau0"=.005, "tau1"=2,
.RNG.name="base::Wichmann-Hill", .RNG.seed=523)
start2 = list("g0"=dnorm(1,0,3), "g1"=rnorm(1,-2,3), "g2"=rnorm(1,0,3), "g3"=rnorm(1,-1,3), "sigma"=5, "ptau0"=.1, "tau1"=3,
.RNG.name="base::Marsaglia-Multicarry", .RNG.seed=57)
start3 = list("g0"=dnorm(1,3,4), "g1"=rnorm(1,0,3), "g2"=rnorm(1,-1,3), "g3"=rnorm(1,0,4), "sigma"=50, "ptau0"=.045, "tau1"=10,
.RNG.name="base::Super-Duper", .RNG.seed=24)
start4 = list("g0"=dnorm(1,-3,10), "g1"=rnorm(1,5,3), "g2"=rnorm(1,5,3), "g3"=rnorm(1,3,4), "sigma"=10, "ptau0"=.10, "tau1"=1,
.RNG.name="base::Mersenne-Twister", .RNG.seed=72100)
start <- list(start1,start2,start3,start4)
model5.runjags <- run.jags(model=model5,
method="parallel",
monitor=c("g0","g1","g2","g3","sigma","ptau0","ptau1","tau0", "tau1"),
data=dataList,
sample=20000,
n.chains=4,
thin=20,
inits=start)
print(model5.runjags)
plot(model5.runjags)
So, we’ll take Model 4 as our final model and get some additional statistics from the code (i.e., draws from posterior distribution).
###############################################################################
# Bayesian Model 4 refinement : random slope + fixed time + rx3+ time*Rx3 #
# 1st: drop time*Rx1 #
# 2nd: drop Rx1 #
###############################################################################
dataList <- list(
y = ano$weight,
time = ano$time,
rx3 = ano$Rx3,
sdY = sd(ano$weight),
n = length(ano$weight),
ng= length(ano$weight)/2,
girl= ano$girl
)
model4 <- "model {
for (i in 1:n) {
y[i] ~ dnorm(mu[i],precision)
mu[i] <- g0 + g1*time[i] + b1j[girl[i]]*time[i] + g3*rx3[i] + g5*time[i]*rx3[i]
yhat[i] <- g0 + g1*time[i] + b1j[girl[i]]*time[i] + g3*rx3[i] + g5*time[i]*rx3[i]
}
for (j in 1:ng) {
b1j[j] ~ dnorm(0,ptau)
}
g0 ~ dnorm(0,1/(100*sdY^2))
g1 ~ dnorm(0,1/(100*sdY^2))
g3 ~ dnorm(0,1/(100*sdY^2))
g5 ~ dnorm(0,1/(100*sdY^2))
tau ~ dunif(0.0001,200)
ptau <- 1/tau^2
sigma ~ dunif(0.0001,2000)
precision <- 1/sigma^2
}"
writeLines(model4, con="model4.txt")
start1 = list("g0"=mean(ano$weight), "g1"=dnorm(1,1,3), "g3"=dnorm(1,0,3),
"g5"=dnorm(1,0,3), "sigma"=sd(ano$weight), "tau"=.5,
.RNG.name="base::Wichmann-Hill", .RNG.seed=523)
start2 = list("g0"=dnorm(1,0,3), "g1"=dnorm(1,-2,3), "g3"=dnorm(1,0,3),
"g5"=dnorm(1,0,3), "sigma"=5, "tau"=1,
.RNG.name="base::Marsaglia-Multicarry", .RNG.seed=57)
start3 = list("g0"=dnorm(1,3,4), "g1"=dnorm(1,0,3), "g3"=dnorm(1,0,3),
"g5"=dnorm(1,0,3), "sigma"=50, "tau"=5,
.RNG.name="base::Super-Duper", .RNG.seed=24)
start4 = list("g0"=dnorm(1,-3,10), "g1"=dnorm(1,5,3),"g3"=dnorm(1,0,3),
"g5"=dnorm(1,3,3), "sigma"=10, "tau"=10,
.RNG.name="base::Mersenne-Twister", .RNG.seed=72100)
start <- list(start1,start2,start3,start4)
model4.runjags <- run.jags(model=model4,
method="parallel",
monitor=c("g0","g1","g3","g5", "sigma", "tau","yhat"),
data=dataList,
sample=20000,
n.chains=4,
thin=5,
inits=start)
## Calling 4 simulations using the parallel method...
## Following the progress of chain 1 (the program will wait for all chains
## to finish before continuing):
## Welcome to JAGS 4.3.0 on Fri Oct 14 10:58:54 2022
## JAGS is free software and comes with ABSOLUTELY NO WARRANTY
## Loading module: basemod: ok
## Loading module: bugs: ok
## . . Reading data file data.txt
## . Compiling model graph
## Resolving undeclared variables
## Allocating nodes
## Graph information:
## Observed stochastic nodes: 144
## Unobserved stochastic nodes: 78
## Total graph size: 967
## . Reading parameter file inits1.txt
## . Initializing model
## . Adapting 1000
## -------------------------------------------------| 1000
## ++++++++++++++++++++++++++++++++++++++++++++++++++ 100%
## Adaptation successful
## . Updating 4000
## -------------------------------------------------| 4000
## ************************************************** 100%
## . . . . . . . . Updating 100000
## -------------------------------------------------| 100000
## ************************************************** 100%
## . . . . Updating 0
## . Deleting model
## .
## All chains have finished
## Simulation complete. Reading coda files...
## Coda files loaded successfully
## Note: Summary statistics were not produced as there are >50 monitored
## variables
## [To override this behaviour see ?add.summary and ?runjags.options]
## FALSEFinished running the simulation
print(model4.runjags)
##
## JAGS model with 80000 samples (thin = 5; chains = 4; adapt+burnin = 5000)
##
## Full summary statistics have not been pre-calculated - use either the summary method or add.summary to calculate summary statistics
summary(model4reml)
## Linear mixed model fit by REML. t-tests use Satterthwaite's method [
## lmerModLmerTest]
## Formula: weight ~ time + treatment + time * treatment + (0 + time | girl)
## Data: ano
##
## REML criterion at convergence: 906
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.59369 -0.46354 -0.00561 0.49016 1.64149
##
## Random effects:
## Groups Name Variance Std.Dev.
## girl time 6.891 2.625
## Residual 22.913 4.787
## Number of obs: 144, groups: girl, 72
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) 79.683 1.988 69.000 40.090 <2e-16 ***
## time 3.007 1.348 104.632 2.230 0.0279 *
## treatment2 2.325 2.891 69.000 0.804 0.4240
## treatment3 -3.718 3.270 69.000 -1.137 0.2594
## time:treatment2 -3.457 1.961 104.632 -1.763 0.0808 .
## time:treatment3 4.258 2.218 104.632 1.920 0.0576 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) time trtmn2 trtmn3 tm:tr2
## time -0.885
## treatment2 -0.688 0.608
## treatment3 -0.608 0.538 0.418
## tim:trtmnt2 0.608 -0.688 -0.885 -0.370
## tim:trtmnt3 0.538 -0.608 -0.370 -0.885 0.418
Why didn’t print(model4.runjags) give you the table of statistics? There are many of them; in particular, there are an extra 72 X 2 = 143 yhat values, 2 values per girl (weight before and weight after).
plot(model4.runjags)
Let’s do some other things with posterior samples. This is a better (more straightforward) than previous version that I had here.
# Takes output and put in format so can use coda plots and diagnostics on it.
samps <- combine.mcmc(model4.runjags)
colnames(samps)
## [1] "g0" "g1" "g3" "g5" "sigma" "tau"
## [7] "yhat[1]" "yhat[2]" "yhat[3]" "yhat[4]" "yhat[5]" "yhat[6]"
## [13] "yhat[7]" "yhat[8]" "yhat[9]" "yhat[10]" "yhat[11]" "yhat[12]"
## [19] "yhat[13]" "yhat[14]" "yhat[15]" "yhat[16]" "yhat[17]" "yhat[18]"
## [25] "yhat[19]" "yhat[20]" "yhat[21]" "yhat[22]" "yhat[23]" "yhat[24]"
## [31] "yhat[25]" "yhat[26]" "yhat[27]" "yhat[28]" "yhat[29]" "yhat[30]"
## [37] "yhat[31]" "yhat[32]" "yhat[33]" "yhat[34]" "yhat[35]" "yhat[36]"
## [43] "yhat[37]" "yhat[38]" "yhat[39]" "yhat[40]" "yhat[41]" "yhat[42]"
## [49] "yhat[43]" "yhat[44]" "yhat[45]" "yhat[46]" "yhat[47]" "yhat[48]"
## [55] "yhat[49]" "yhat[50]" "yhat[51]" "yhat[52]" "yhat[53]" "yhat[54]"
## [61] "yhat[55]" "yhat[56]" "yhat[57]" "yhat[58]" "yhat[59]" "yhat[60]"
## [67] "yhat[61]" "yhat[62]" "yhat[63]" "yhat[64]" "yhat[65]" "yhat[66]"
## [73] "yhat[67]" "yhat[68]" "yhat[69]" "yhat[70]" "yhat[71]" "yhat[72]"
## [79] "yhat[73]" "yhat[74]" "yhat[75]" "yhat[76]" "yhat[77]" "yhat[78]"
## [85] "yhat[79]" "yhat[80]" "yhat[81]" "yhat[82]" "yhat[83]" "yhat[84]"
## [91] "yhat[85]" "yhat[86]" "yhat[87]" "yhat[88]" "yhat[89]" "yhat[90]"
## [97] "yhat[91]" "yhat[92]" "yhat[93]" "yhat[94]" "yhat[95]" "yhat[96]"
## [103] "yhat[97]" "yhat[98]" "yhat[99]" "yhat[100]" "yhat[101]" "yhat[102]"
## [109] "yhat[103]" "yhat[104]" "yhat[105]" "yhat[106]" "yhat[107]" "yhat[108]"
## [115] "yhat[109]" "yhat[110]" "yhat[111]" "yhat[112]" "yhat[113]" "yhat[114]"
## [121] "yhat[115]" "yhat[116]" "yhat[117]" "yhat[118]" "yhat[119]" "yhat[120]"
## [127] "yhat[121]" "yhat[122]" "yhat[123]" "yhat[124]" "yhat[125]" "yhat[126]"
## [133] "yhat[127]" "yhat[128]" "yhat[129]" "yhat[130]" "yhat[131]" "yhat[132]"
## [139] "yhat[133]" "yhat[134]" "yhat[135]" "yhat[136]" "yhat[137]" "yhat[138]"
## [145] "yhat[139]" "yhat[140]" "yhat[141]" "yhat[142]" "yhat[143]" "yhat[144]"
g0 <- samps[,1]
g1 <- samps[,2]
g3 <- samps[,3]
g5 <- samps[,4]
sigma <- samps[,5]
tau <- samps[,6]
fitted <- samps[,7:150]
ano$yhat <- apply(fitted,2,"mean")
plot(ano$time,ano$yhat,
type="n",
ylim=c(65,104),
xlab="Before/After Treatment",
ylab="Weight in Pounds",
main="Bayesian refined Model 4",
xaxt="n"
)
axis(1, at = seq(1,2,by=1),labels=c("Before","After"))
for (i in 1:n){
g <- subset(ano,ano$girl==i)
lines(g$time, g$yhat, col=i)
}
This graph of fitted values resembles pattern in the data.
More methods for checked convergence should be done.