library(mvtnorm)
library(gee)
library(lattice)
#Initial parameters
set.seed(1996)
n = 10 #observations per subject
m = 25 #number of subjects
beta = c(10,0) #Beta vector
t = 1:10 #times tij
Mean.model = beta[1] + beta[2] * t
### Functions to generate data
##Random Intercepts
RI.data = function(sigma, tau, n=10, t.ij){
b0i = rnorm(m, mean = 0, sd = tau)
b0i = rep(b0i, rep(n,m))
epsilon = rnorm((n*m), mean = 0, sd = sigma )
Y = rep(Mean.model, m) + b0i + epsilon
return( data.frame(id=rep(1:m,each=n),
y=Y,
t.ij=rep(t.ij,m)))}
##Random Intercepts and Slopes
RIS.data = function(sigma,D, n=10, t.ij){
bi = rmvnorm(m,mean = c(0, 0),sigma = D )
b0i = rep(bi[,1], rep(n, m))
b1i = rep(bi[,2], rep(n, m))
epsilon = rnorm((n*m), mean = 0, sd = sigma )
Y = rep( Mean.model, m ) + b0i + ( b1i * rep(t, m) ) + epsilon
return( data.frame(id=rep(1:m,each=n),
y=Y,
t.ij=rep(t.ij,m)))}
## Serial Correlation
SC.data = function( sigma, tau, rho, n=10, t.ij){
Sigma = matrix( tau^2, nrow = n, ncol = n ) + diag( rep(sigma^2, n) )
for( i in 1:n ){
for( j in 1:n ){
Sigma[i,j] = Sigma[i,j] * rho^(abs(i-j))}}
return(data.frame( id=rep(1:m,each=n),y=as.vector(t(rmvnorm( m, Mean.model,
sigma = Sigma))),t.ij=rep(t.ij,m)))}
#Random intercept model plots
#par(mfrow=c(1,3))
data.ri= RI.data(sigma=1,tau=1,n=10,t.ij=t)
ri.11=plot(y~t.ij,data=data.ri,xlab="tij",ylab="Yi",col="gray50",
main="Sigma=1, Tau=1")
for (i in 1:25){lines(data.ri$t.ij[data.ri$id==i],
data.ri$y[data.ri$id==i],lwd=1.5)}
with (data.ri, {lines(supsmu(t.ij,y),lty=5,col="red",lwd=2)})
data.ri= RI.data(sigma=1,tau=2,n=10,t.ij=t)
ri.12=plot(y~t.ij,data=data.ri,xlab="tij",ylab="Yi",col="gray50",
main="Sigma=1, Tau=2")
for (i in 1:25){lines(data.ri$t.ij[data.ri$id==i],
data.ri$y[data.ri$id==i],lwd=1.5)}
with (data.ri, {lines(supsmu(t.ij,y),lty=5,col="red",lwd=2)})
data.ri= RI.data(sigma=1,tau=5,n=10,t.ij=t)
ri.15=plot(y~t.ij,data=data.ri,xlab="tij",ylab="Yi",col="gray50",
main= "Sigma=1, Tau=5")
for (i in 1:25){lines(data.ri$t.ij[data.ri$id==i],
data.ri$y[data.ri$id==i],lwd=1.5)}
with (data.ri, {lines(supsmu(t.ij,y),lty=5,col="red",lwd=2)})
\(Var(Y_{i})\) for the random intercept model is \(Var(b_{0,1}) + Var(\epsilon_{ij})=\tau^2 + \sigma^2\). \(Cov(Y_{ij},Y_{ik}) = Cov(b_{0,i}+\epsilon_{ij},b_{0,i}+\epsilon_{ij})=Cov(b_{0,i},b_{0,i})=\tau^2\). So \(Cov(Y_{i})\) has \(\tau^2 + \sigma^2\) on the diagonals and \(\tau^2\) on the off diagonals.
#Random intercept and slope model plots
#par(mfrow=c(1,3))
data.ris= RIS.data(sigma=1,D=matrix(c(2,0,0,2),nrow=2,ncol=2),n=10,t.ij=t)
ris.1=plot(y~t.ij,data=data.ri,xlab="tij",ylab="Yi",col="gray50",
main="RIS 1")
for (i in 1:25){lines(data.ris$t.ij[data.ris$id==i],data.ris$y[data.ris$id==i],lwd=1.5)}
with (data.ris, {lines(supsmu(t.ij,y),lty=5,col="red",lwd=2)})
data.ris= RIS.data(sigma=1,D=matrix(c(2,-2,-2,2),nrow=2,ncol=2),n=10,t.ij=t)
ris.2=plot(y~t.ij,data=data.ri,xlab="tij",ylab="Yi",col="gray50",
main="RIS 2")
for (i in 1:25){lines(data.ris$t.ij[data.ris$id==i],data.ris$y[data.ris$id==i],lwd=1.5)}
with (data.ris, {lines(supsmu(t.ij,y),lty=5,col="red",lwd=2)})
data.ris= RIS.data(sigma=1,D=matrix(c(.5,0,0,.4),nrow=2,ncol=2),n=10,t.ij=t)
ris.3=plot(y~t.ij,data=data.ri,xlab="tij",ylab="Yi",col="gray50",
main="RIS 3")
for (i in 1:25){lines(data.ris$t.ij[data.ris$id==i],data.ris$y[data.ris$id==i],lwd=1.5)}
with (data.ris, {lines(supsmu(t.ij,y),lty=5,col="red",lwd=2)})
\(Var(Y_{i})= Var(b_{0,1})+2t_{ij}Cov(b_{0i},b_{1i})+t_{ij}^2Var(b_{1i})+Var(\epsilon_{ij}) = Var(b_{0,1})+2t_{ij}Cov(b_{0i},b_{1i})+t_{ij}^2Var(b_{1i})+\sigma^2\), where \(Var(b_{0,1})\) and \(Var(b_{1i})\) are the diagonals of D (\(d_{11}, d_{22}\)) and the covariance are the off-diagonals (\(d_{12}\)). The \(Cov(Y_{ij},Y_{ik})=d_{11}+(t_{ij}+t_{ik})d_{12}+t_{ij}t_{ik}d_{22}\).
####### Serial Correlation
data.sc= SC.data(sigma=1, tau=2, rho=.7, n=10, t.ij=t)
SC.12.7=plot(y~t.ij,data=data.sc,xlab="tij",ylab="Yi",col="gray50",
main="s=1,tau=2,rho=.7")
for (i in 1:25){lines(data.sc$t.ij[data.sc$id==i],data.sc$y[data.sc$id==i],lwd=1.5)}
with (data.sc, {lines(supsmu(t.ij,y),lty=5,col="red",lwd=2)})
data.sc= SC.data(sigma=1, tau=2, rho=.9, n=10, t.ij=t)
SC.12.9=plot(y~t.ij,data=data.sc,xlab="tij",ylab="Yi",col="gray50",
main="s=1,tau=2,rho=.7")
for (i in 1:25){lines(data.sc$t.ij[data.sc$id==i],data.sc$y[data.sc$id==i],lwd=1.5)}
with (data.sc, {lines(supsmu(t.ij,y),lty=5,col="red",lwd=2)})
data.sc= SC.data(sigma=2, tau=2, rho=.9, n=10, t.ij=t)
SC.22.9=plot(y~t.ij,data=data.sc,xlab="tij",ylab="Yi",col="gray50",
main="s=1,tau=2,rho=.7")
for (i in 1:25){lines(data.sc$t.ij[data.sc$id==i],data.sc$y[data.sc$id==i],lwd=1.5)}
with (data.sc, {lines(supsmu(t.ij,y),lty=5,col="red",lwd=2)})
##3. FEV1 data analysis
#Open libraries and data
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(mvtnorm)
library(gee)
library(lattice)
library(nlme)
##
## Attaching package: 'nlme'
## The following object is masked from 'package:dplyr':
##
## collapse
#Open and wrangle data
fev1 = read.table("~/Biostat 3rd Year/Fall - Longitudinal/8452 Datasets/fev1.dat",
quote="\"", comment.char="")
names(fev1) = c("id","height","age","base.height","base.age","l.fev1")
fev1$t.ij <- fev1$age - fev1$base.age #time
fev1$id=factor(fev1$id)
fev1$c.age = fev1$age-fev1$base.age #change in age variable
summary(fev1)
## id height age base.height
## 18 : 12 Min. :1.110 Min. : 6.434 Min. :1.110
## 23 : 12 1st Qu.:1.370 1st Qu.: 9.717 1st Qu.:1.220
## 35 : 12 Median :1.540 Median :12.595 Median :1.260
## 38 : 12 Mean :1.497 Mean :12.566 Mean :1.276
## 39 : 12 3rd Qu.:1.620 3rd Qu.:15.366 3rd Qu.:1.320
## 40 : 12 Max. :1.790 Max. :18.691 Max. :1.720
## (Other):1922
## base.age l.fev1 t.ij c.age
## Min. : 6.434 Min. :-0.6932 Min. : 0.000 Min. : 0.000
## 1st Qu.: 7.136 1st Qu.: 0.5481 1st Qu.: 1.074 1st Qu.: 1.074
## Median : 7.781 Median : 0.8671 Median : 4.108 Median : 4.108
## Mean : 8.030 Mean : 0.8152 Mean : 4.536 Mean : 4.536
## 3rd Qu.: 8.449 3rd Qu.: 1.0978 3rd Qu.: 7.140 3rd Qu.: 7.140
## Max. :14.067 Max. : 1.5953 Max. :11.061 Max. :11.061
##
#summary(fev1$base.age)
hist(fev1$base.age)
hist(fev1$l.fev1)
summary(fev1$age)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 6.434 9.717 12.595 12.566 15.366 18.691
#######Basic scatter plots##########
par(mfrow=c(1,3))
plot(l.fev1~base.age, data=fev1,pch=".",xlab="Baseline Age",
ylab="Log(FEV1)")
with (fev1,{lines(supsmu(base.age,l.fev1),lty=5,col="red",lwd=2)})
#Among 7-9 year olds
subset=which(fev1$base.age<10)
plot(fev1$l.fev1[subset]~fev1$base.age[subset],pch=".",xlab="Baseline Age under 10",
ylab="Log(FEV1)")
with (fev1,{lines(supsmu(base.age[subset],l.fev1[subset]),lty=5,col="red",lwd=2)})
plot(l.fev1~c.age, data=fev1,pch=".",xlab="Change in Age",
ylab="Log(FEV1)")
with (fev1,{lines(supsmu(c.age,l.fev1),lty=5,col="red",lwd=2)})
plot(l.fev1[subset]~c.age[subset], data=fev1,pch=".",xlab="Change in Age for girls starting at age 10",
ylab="Log(FEV1)")
with (fev1,{lines(supsmu(c.age[subset],l.fev1[subset]),lty=5,col="red",lwd=2)})
plot(l.fev1~height, data=fev1,pch=".",xlab="Height",
ylab="Log(FEV1)")
plot(l.fev1~t.ij, data=fev1,pch=".",xlab="Annual examination (tij)",
ylab="Log(FEV1)")
with (fev1,{lines(supsmu(t.ij,l.fev1),lty=5,col="red",lwd=2)})
plot(height~age,data=fev1)
###### Spaghetti plot #####
xyplot (l.fev1 ~ t.ij, data = fev1, type = "b", group = id,
xlab = "Annual examiniation (tij)",
ylab = "Log(FEV1)",
col.line = "gray20")
#Plot by baseline age
xyplot (l.fev1 ~ base.age | equal.count (base.age, 4), data = fev1,
type = "l", group = id,
xlab = "Annual examination (tij)",
col.line = "gray20",
ylab = "Log(FEV1)",
strip = strip.custom (var.name = "Baseline Age"))
#Plot by age
xyplot (l.fev1 ~ age | equal.count (age, 4), data = fev1,
type = "l", group = id,
xlab = "Annual examination (tij)",
col.line = "gray20",
ylab = "Log(FEV1)",
strip = strip.custom (var.name = "Age"))
#Plot by height
xyplot (l.fev1 ~ height | equal.count (height, 4), data = fev1,
type = "l", group = id,
xlab = "Annual examination (tij)",
col.line = "gray20",
ylab = "Log(FEV1)",
strip = strip.custom (var.name = "Height"))
The maximum followup period was 11 years, while the median followup was near 4.The baseline age ranged from 6 to 14 years old while the majority of the subjects were between 7-8 years old at study entry. At baseline, the age did not have an effect on log(fev1) but as the change in age increased the log(fev1) slightly increased, the same trend as follow-up time. This could be due to the small variability among baseline ages, but from this data it seems that there is a stronger longitudinal effect compared to the cross-sectional effect of age. Height seems correlated with log(fev1) as well, so a model including both age and height might be optimal.
#Source: this code is from Professor Luo's lecture notes
fev1.lm <- lm (l.fev1 ~ t.ij, data = fev1)
fev1$lmres <- resid (fev1.lm)
fev1$roundyr <- round (fev1$t.ij)
## Reshape the data to wide format
fev1w <- reshape (fev1[,c("id", "lmres", "roundyr")],
direction = "wide",
v.names = "lmres", timevar = "roundyr",
idvar = "id")
#Put histograms on the diagonal
panel.hist <- function(x, ...) {
usr <- par("usr"); on.exit(par(usr))
par(usr = c(usr[1:2], 0, 1.5) )
h <- hist(x, plot = FALSE)
breaks <- h$breaks;
nB <- length(breaks)
y <- h$counts;
y <- y/max(y)
rect(breaks[-nB], 0, breaks[-1], y, col="cyan", ...)}
## Put (absolute) correlations on the upper panel,
#w/ size prop. to correlation.
panel.cor <- function(x, y, digits=2, prefix="", cex.cor)
{
usr <- par("usr"); on.exit(par(usr))
par(usr = c(0, 1, 0, 1))
r <- abs (cor(x, y, use = "pairwise.complete.obs"))
txt <- format(c(r, 0.123456789), digits=digits)[1]
txt <- paste(prefix, txt, sep="")
if(missing(cex.cor)) cex <- 0.8/strwidth(txt)
text(0.5, 0.5, txt, cex = cex * r)
}
pairs (fev1w[,c(5,2,3,6:9)], upper.panel = panel.cor,
diag.panel = panel.hist)
From the correlation histogram, the correlations for farther observations are only slight smaller than closer observations and the correlations are constant along the diagonal. There may be evidence of strong within subject correlation consistently over time which would make a random effects model appealing.
#Source: Professor Luo's lecture code
lda.vg <- function (id, res, time, plot = TRUE, ...) {
vv <- tapply (res, id,
function (x) outer(x, x, function(x, y) (x - y)^2/2))
v <- unlist (lapply (vv, function (x) x[lower.tri (x)]))
uu <- tapply (time, id,
function (x) outer (x, x, function (x, y) (x - y)))
u <- unlist (lapply (uu, function (x) x[lower.tri (x)]))
if (plot) {
vg.loess <- loess.smooth (u, v, family = "gaussian")
plot (v ~ u, pch = ".", col = "gray50", ...)
lines (vg.loess, lty = 1)
abline (h = var (res), lty = 2)
}
invisible (data.frame (v = v, u = u))
}
lda.vg (fev1$id, fev1$lmres, fev1$t.ij,
ylim = c(0, .05), ylab = "", xlab = "",main="Variogram of Log(FEV1) residuals")
There is a smooth rise which levels off at the 6 year followup after which it decreases. This trend may be due to the lack of data for longer follow-up times. There does not seem to be a large autocorrelation effect.
#OLS model
fev1.age.lm = lm(l.fev1~base.age+c.age,data=fev1)
summary(fev1.age.lm)
##
## Call:
## lm(formula = l.fev1 ~ base.age + c.age, data = fev1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.21787 -0.10089 0.00294 0.11044 0.58188
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -0.312591 0.026447 -11.82 <2e-16 ***
## base.age 0.091648 0.003077 29.79 <2e-16 ***
## c.age 0.086395 0.001106 78.13 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.162 on 1991 degrees of freedom
## Multiple R-squared: 0.7599, Adjusted R-squared: 0.7597
## F-statistic: 3151 on 2 and 1991 DF, p-value: < 2.2e-16
#GLS with baseline age and change in age as covariates
fev1.ind=gls(l.fev1~base.age+c.age,data=fev1,method="ML")
summary(fev1.ind) #same as OLS as expected
## Generalized least squares fit by maximum likelihood
## Model: l.fev1 ~ base.age + c.age
## Data: fev1
## AIC BIC logLik
## -1594.15 -1571.759 801.0751
##
## Coefficients:
## Value Std.Error t-value p-value
## (Intercept) -0.31259141 0.026446775 -11.81964 0
## base.age 0.09164756 0.003076561 29.78896 0
## c.age 0.08639534 0.001105816 78.12811 0
##
## Correlation:
## (Intr) base.g
## base.age -0.973
## c.age -0.381 0.205
##
## Standardized residuals:
## Min Q1 Med Q3 Max
## -7.52163837 -0.62308337 0.01815619 0.68207352 3.59375231
##
## Residual standard error: 0.1619154
## Degrees of freedom: 1994 total; 1991 residual
anova(fev1.ind)
## Denom. DF: 1991
## numDF F-value p-value
## (Intercept) 1 50474.65 <.0001
## base.age 1 198.54 <.0001
## c.age 1 6104.00 <.0001
fev1.ar1=gls(l.fev1~base.age+c.age,data=fev1,correlation = corAR1 (form = ~ 1 | id),method="ML")
summary(fev1.ar1)
## Generalized least squares fit by maximum likelihood
## Model: l.fev1 ~ base.age + c.age
## Data: fev1
## AIC BIC logLik
## -3549.482 -3521.492 1779.741
##
## Correlation Structure: AR(1)
## Formula: ~1 | id
## Parameter estimate(s):
## Phi
## 0.84388
##
## Coefficients:
## Value Std.Error t-value p-value
## (Intercept) -0.3975811 0.05143645 -7.72956 0
## base.age 0.0962926 0.00610036 15.78475 0
## c.age 0.0867535 0.00126949 68.33736 0
##
## Correlation:
## (Intr) base.g
## base.age -0.983
## c.age -0.213 0.122
##
## Standardized residuals:
## Min Q1 Med Q3 Max
## -6.9871403 -0.3398216 0.2955394 0.9289907 3.7392820
##
## Residual standard error: 0.1682115
## Degrees of freedom: 1994 total; 1991 residual
anova(fev1.ar1)
## Denom. DF: 1991
## numDF F-value p-value
## (Intercept) 1 8134.326 <.0001
## base.age 1 55.843 <.0001
## c.age 1 4669.995 <.0001
fev1.exch=gls(l.fev1~base.age+c.age,data=fev1,correlation = corCompSymm (form = ~ 1 | id),method="ML")
summary(fev1.exch)
## Generalized least squares fit by maximum likelihood
## Model: l.fev1 ~ base.age + c.age
## Data: fev1
## AIC BIC logLik
## -2733.243 -2705.254 1371.622
##
## Correlation Structure: Compound symmetry
## Formula: ~1 | id
## Parameter estimate(s):
## Rho
## 0.6306421
##
## Coefficients:
## Value Std.Error t-value p-value
## (Intercept) -0.3202265 0.05167466 -6.19697 0
## base.age 0.0915820 0.00614303 14.90828 0
## c.age 0.0857247 0.00074700 114.75920 0
##
## Correlation:
## (Intr) base.g
## base.age -0.986
## c.age -0.124 0.071
##
## Standardized residuals:
## Min Q1 Med Q3 Max
## -7.18644465 -0.53769923 0.08346109 0.72605748 3.51756260
##
## Residual standard error: 0.1683217
## Degrees of freedom: 1994 total; 1991 residual
anova(fev1.exch)
## Denom. DF: 1991
## numDF F-value p-value
## (Intercept) 1 8274.091 <.0001
## base.age 1 45.867 <.0001
## c.age 1 13169.675 <.0001
anova(fev1.exch,fev1.ind,fev1.ar1)
## Model df AIC BIC logLik Test L.Ratio p-value
## fev1.exch 1 5 -2733.243 -2705.254 1371.6215
## fev1.ind 2 4 -1594.150 -1571.759 801.0751 1 vs 2 1141.093 <.0001
## fev1.ar1 3 5 -3549.482 -3521.492 1779.7410 2 vs 3 1957.332 <.0001
The liklihood ratio statistic indiciates that the exchangeable correlation structure fits the model better than the other two correlation structures, however, the AIC and BIC were the lowest for the model with an independent correlation structure. The \(\hat{B}\)’s obtained are almost identical but the model with the exchangeable correlation structure had the smallest standard errors. The interpreation of \(\hat{B_{c}}\) is the associated effect of a one-year age difference on log(fev1) between subjects while \(\hat{B_{l}}\) is the associated effect of a one-year age difference on log(fev1) within a subject. So consistent among the models, a one-year increase in age is associated with a .092 (\(\hat{B_{c}}\)) increase in log(fev1) units across subjects. And a one-year increase in age within a subject is associated with a .086 (\(\hat{B_{l}}\)) increase in log(fev1) units.
#GLS with just age as a covariate
fev1.ind.age=gls(l.fev1~age,data=fev1,method="ML")
summary(fev1.ind.age) #same as OLS as expected
## Generalized least squares fit by maximum likelihood
## Model: l.fev1 ~ age
## Data: fev1
## AIC BIC logLik
## -1593.18 -1576.386 799.59
##
## Coefficients:
## Value Std.Error t-value p-value
## (Intercept) -0.27415161 0.014204180 -19.30077 0
## age 0.08669269 0.001092802 79.33066 0
##
## Correlation:
## (Intr)
## age -0.967
##
## Standardized residuals:
## Min Q1 Med Q3 Max
## -7.47389430 -0.62201592 0.01233673 0.69096950 3.59045752
##
## Residual standard error: 0.162036
## Degrees of freedom: 1994 total; 1992 residual
anova(fev1.ind.age)
## Denom. DF: 1992
## numDF F-value p-value
## (Intercept) 1 50424.83 <.0001
## age 1 6293.35 <.0001
fev1.ar1.age=gls(l.fev1~age,data=fev1,correlation = corAR1 (form = ~ 1 | id),method="ML")
summary(fev1.ar1.age)
## Generalized least squares fit by maximum likelihood
## Model: l.fev1 ~ age
## Data: fev1
## AIC BIC logLik
## -3549.017 -3526.625 1778.508
##
## Correlation Structure: AR(1)
## Formula: ~1 | id
## Parameter estimate(s):
## Phi
## 0.8441701
##
## Coefficients:
## Value Std.Error t-value p-value
## (Intercept) -0.3215129 0.017158098 -18.73826 0
## age 0.0869263 0.001265508 68.68884 0
##
## Correlation:
## (Intr)
## age -0.884
##
## Standardized residuals:
## Min Q1 Med Q3 Max
## -6.9213475 -0.3363911 0.2737771 0.9242987 3.7199736
##
## Residual standard error: 0.1684373
## Degrees of freedom: 1994 total; 1992 residual
anova(fev1.ar1.age)
## Denom. DF: 1992
## numDF F-value p-value
## (Intercept) 1 8109.537 <.0001
## age 1 4718.157 <.0001
fev1.exch.age=gls(l.fev1~age,data=fev1,correlation = corCompSymm (form = ~ 1 | id),method="ML")
summary(fev1.exch.age)
## Generalized least squares fit by maximum likelihood
## Model: l.fev1 ~ age
## Data: fev1
## AIC BIC logLik
## -2734.332 -2711.94 1371.166
##
## Correlation Structure: Compound symmetry
## Formula: ~1 | id
## Parameter estimate(s):
## Rho
## 0.6316071
##
## Coefficients:
## Value Std.Error t-value p-value
## (Intercept) -0.27228701 0.01220589 -22.30784 0
## age 0.08575976 0.00074586 114.98105 0
##
## Correlation:
## (Intr)
## age -0.732
##
## Standardized residuals:
## Min Q1 Med Q3 Max
## -7.14617793 -0.53945421 0.07136997 0.72234872 3.50165275
##
## Residual standard error: 0.168535
## Degrees of freedom: 1994 total; 1992 residual
anova(fev1.exch.age)
## Denom. DF: 1992
## numDF F-value p-value
## (Intercept) 1 8247.362 <.0001
## age 1 13220.643 <.0001
anova(fev1.exch.age,fev1.ind.age,fev1.ar1.age)
## Model df AIC BIC logLik Test L.Ratio p-value
## fev1.exch.age 1 4 -2734.332 -2711.940 1371.166
## fev1.ind.age 2 3 -1593.180 -1576.386 799.590 1 vs 2 1143.152 <.0001
## fev1.ar1.age 3 4 -3549.017 -3526.625 1778.508 2 vs 3 1957.836 <.0001
The estimates among the three models were again almost identical with the exchangeavle correlation structure model having the smallest standard errors for the estimates. This model does not adjust for age at baseline/is not contstrained like the previous model, but the estimate of the association between a one-year increase in age and log(fev1) is essentially identical for these three models and the three contrained models. I would argue that the cross-sectional effect of age does not need to be adjusted for. From the scatter plots above, the mean log(fev1) is fairly constant with increases in baseline age.
#Model diagnostics
plot(fev1.ind,id~resid(.),main="Model 1 Ind")
plot(fev1.ind.age,id~resid(.),main="Model 2 Ind")
plot(fev1.exch,id~resid(.),main="Model 1 Exch")
plot(fev1.exch.age,id~resid(.),main="Model 2 Exch")
plot(fev1.ar1,id~resid(.), main="Model 1 AR1")
plot(fev1.ar1.age,id~resid(.),"Model 2 AR1")
## Warning in panel.abline(v = abl[1], ...): NAs introduced by coercion
## Warning in unit(x0, default.units): NAs introduced by coercion
## Warning in unit(x1, default.units): NAs introduced by coercion
plot (fev1.exch, resid (.) ~ age, abline = 0,main="Model 1 Exch")
plot (fev1.ind, resid (.) ~ age, abline = 0, main="Model 1 Ind")
plot (fev1.ar1, resid (.) ~ age, abline = 0,main="Model 1 AR1")
plot (fev1.exch.age, resid (.) ~ age, abline = 0,main="Model 2 Exch")
plot (fev1.ind.age, resid (.) ~ age, abline = 0, main= "Model 2 Ind")
plot (fev1.ar1.age, resid (.) ~ age, abline = 0,main="Model 2 AR1")
qqnorm (fev1.exch, abline = c(0,1),main="Model 1 Exch")
qqnorm (fev1.ind, abline = c(0,1), main="Model 1 Ind")
qqnorm (fev1.ar1, abline = c(0,1),main="Model 1 AR1")
qqnorm (fev1.exch.age, abline = c(0,1),main="Model 2 Exch")
qqnorm (fev1.ind.age, abline = c(0,1), main= "Model 2 Ind")
qqnorm (fev1.ar1.age, abline = c(0,1),main="Model 2 AR1")
anova(fev1.ind,fev1.ind.age,fev1.exch,fev1.exch.age,fev1.ar1,fev1.ar1.age)
## Model df AIC BIC logLik Test L.Ratio p-value
## fev1.ind 1 4 -1594.150 -1571.759 801.0751
## fev1.ind.age 2 3 -1593.180 -1576.386 799.5900 1 vs 2 2.9701 0.0848
## fev1.exch 3 5 -2733.243 -2705.254 1371.6215 2 vs 3 1144.0630 <.0001
## fev1.exch.age 4 4 -2734.332 -2711.940 1371.1660 3 vs 4 0.9110 0.3398
## fev1.ar1 5 5 -3549.482 -3521.492 1779.7410 4 vs 5 817.1499 <.0001
## fev1.ar1.age 6 4 -3549.017 -3526.625 1778.5083 5 vs 6 2.4654 0.1164
Model diagnostics and an anova comparing all the models were ran. Based on the anova table, the AIC and BIC were the lowest for the model with only the age covariate that had an independence correlation structure but this has to do with the df. The AR(1) model for both sets of variables performs the worst based on AIC and BIC. I would choose the exchangeable correlation structure models because there seems to be strong within subject correlation that does not dissipate over time although the AIC/BIC is higher for than the independent structure models. Among the covariates, based on this data I would choose the unconstrained model with only age that ignores any baseline differences in log(fev1). However, given the pairwise correlations between height, age and log(fev1) it may be worthwhile to include height in the model along with age.