Lecture 48 (lab 12b)—April 12, 2006

What was covered?

R functions and commands demonstrated

R function options

R packages used

Adding Additional Random Effects

> #obtain data
> inverts<- read.table('http://www.unc.edu/courses/2006spring/ecol/145/001/data/lab11/74species.csv', sep=',', header=TRUE)
> names(inverts)
 [1] "species"      "meantemp" "temp"  "PLD" "taxon"   "climate.3"
 [7] "feeding.type" "lntemp"   "lnPLD" "n"   "PLD.15c" "lnPLD.15c"
[13] "X1000.k"      "lograte"

or in composite form

random = ~1 + x + x^2|species

where as usual explicit listing of the intercept is actually unnecessary.

> library(nlme)
> #random slopes and intercepts
> model4a<-lme(lnPLD~I(lntemp-log(15))+ I((lntemp-log(15))^2), random=~I(log(temp)-log(15))|species, data=inverts, method='ML')
> #random constant, linear, and quadratic terms
> model4b<-lme(lnPLD~I(lntemp-log(15))+I((lntemp-log(15))^2), random=~I(log(temp)-log(15))+ I((log(temp)-log(15))^2)|species, control=lmeControl(maxIter=200, msMaxIter=200, niterEM=100, msVerbose=TRUE), data=inverts, method='ML')

random=~I(log(temp)-log(15))+ I((log(temp)-log(15))^2)|species

> anova(model4a,model4b)
        Model df      AIC      BIC    logLik   Test L.Ratio p-value
model4a     1  7 199.2543 222.9457 -92.62713
model4b     2 10 196.1266 229.9715 -88.06329 1 vs 2 9.12768  0.0276

So we see that the likelihood ratio test is significant at the .05 level and that there has been a moderate decrease in AIC. This suggests that we should include random effects for all three level-1 parameters.

> .5*(1-pchisq(9.12768,3)) + .5*(1-pchisq(9.12768,2))
[1] 0.01903128

so in this instance our conclusion does not change.

Normality assumptions

,  

Fig. 1   Assessing normality of the level-1 residuals

where the level-1 residuals are independent of the level-2 residuals. Notice that the level-2 residuals technically should have a multivariate normal distribution with the given covariance matrix.

> library(car)
> qq.plot(residuals(model4b, type='pearson'), label=inverts$species)

> dim(inverts)
[1] 218 14
> .05*218
[1] 10.9

So we expect roughly 11 observations to fall outside of the bands. Since this is exactly what we observe and the residual plot otherwise looks fairly straight, we find no evidence to suggest the level-1 residuals are non-normal in their distribution.

> ranef(model4b)[1:5,]
                     (Intercept) I(log(temp) - log(15)) I((log(temp) - log(15))^2)
Amphiprion melanopus   0.1392374            -0.07367379               -0.031719350
Armases miersii        0.5504058            -0.19963899               -0.080403607
Balanus amphitrite 1  -0.2595831             0.16854758                0.074450184
Balanus eburneus      -0.7385579             0.04149017               -0.003295344
Balanus trigonus      -0.6313596            -0.16718955               -0.102341535

> qq.plot(ranef(model4b)[,1], ylab=expression(u["0 i"]))
> qq.plot(ranef(model4b)[,2], ylab=expression(u["1 i"]))
> qq.plot(ranef(model4b)[,3], ylab=expression(u["2 i"]))

   

Fig. 2  Assessing whether the marginal distributions of the level-2 random effects are univariate normal

Multilevel models with three hierarchical levels

Visualizing the data

> apples<- read.table('http://www.unc.edu/courses/2006spring/ecol/145/001/data/lab12/AppleData.csv',
sep=',', header=TRUE)
> new.apples<-apples[,c("TREE", "APPLE", "appleid", "time", "diam")]
> new.grp<-groupedData(diam~time|TREE/APPLE, data=new.apples)

> library(lattice)
> #change background color to white
> trellis.par.set(col.whitebg())
> plot(new.grp)

That's not too exciting. Fortunately there are additional options available.

> plot(new.grp,display=1)

Fig. 4  Trajectories grouped by the highest level

> plot(new.grp,display=1,collapse=1)

    

Fig. 5  Trajectories collapsed to the tree mean

Fitting the models

or in composite form

where , , and . Using the same notation explained above for the 3-level groupedData object, we fit the model in R as follows.

> model0a<-lme(diam~1, random=~1|TREE/APPLE, data=new.apples, method='ML', na.action=na.omit)
> AIC(model0a)
[1] -1092.074
> VarCorr(model0a)

            Variance     StdDev
TREE =      pdLogChol(1)
(Intercept) 0.0001511123 0.01229278
APPLE =     pdLogChol(1)
(Intercept) 0.0093915920 0.09691023
Residual    0.0030494623 0.05522194

> 0.0001511123/(0.0001511123+0.0093915920+0.0030494623)
[1] 0.0120005

The fraction of the total variance that is attributable to variation between apples on the same tree is

> 0.0093915920/(0.0001511123+0.0093915920+0.0030494623)
[1] 0.7458281

Finally the fraction of the total variance that is due to variation between different observations on the same apple is

> 0.0030494623/(0.0001511123+0.0093915920+0.0030494623)
[1] 0.2421714

> model1a<-lme(diam~time,random=list(TREE=~1,APPLE=~time), data=new.apples, method='ML', na.action=na.omit)

> AIC(model1a)
[1] -1918.749
> VarCorr(model1a)
            Variance       StdDev       Corr
TREE =      pdLogChol(1)
(Intercept) 4.483999e-07   0.0006696267
APPLE =     pdLogChol(time)
(Intercept) 7.847503e-03   0.0885861352 (Intr)
time        5.183084e-05   0.0071993638 0.542
Residual    2.614533e-04   0.0161695169

> model2a<-lme(diam~time, random=list(TREE=~time, APPLE=~time), data=new.apples, method='ML', na.action=na.omit)
> VarCorr(model2a)
            Variance StdDev Corr
TREE =      pdLogChol(time)
(Intercept) 1.658243e-04 0.012877278 (Intr)
time        1.290148e-05 0.003591863 0.978
APPLE =     pdLogChol(time)
(Intercept) 7.693197e-03 0.087710869 (Intr)
time        3.880095e-05 0.006229041 0.537
Residual    2.612330e-04 0.016162703

> model2a<-lme(diam~time, random=~time|TREE/APPLE, data=new.apples, method='ML', na.action=na.omit)

> model3a<-lme(diam~time, random=list(TREE=~time, APPLE=~time), data=new.apples, method='ML', na.action=na.omit, correlation=corAR1())

> sapply(list(model0a, model1a, model2a, model3a), AIC)
[1] -1092.074 -1918.749 -1920.624 -1935.087

> model3<-lme(diam~time, random=~time|appleid, data=new.apples, method='ML', na.action=na.omit, correlation=corAR1())
> AIC(model3)

[1] -1936.372

Multilevel models using the lme4 package (not done in class)

> library(lme4)
> lmer(diam~time+(time|appleid), data=new.apples, method='ML', na.action=na.omit)

Notice that there is no random statement. Instead random effects are entered as if they were ordinary predictors with the exception that the grouping variable is included as part of the predictor name and the entire term, random effect vertical bar grouping factor, is enclosed in parentheses. When an additional level is added, for example TREE, that level just appears as another random predictor in the equation.

> apply(table(apples$APPLE, apples$TREE), 1, function(x) sum(x>0))
1 2 3 4 5 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
4 4 2 3 4 2 3 4  5  4  3  1  3  3  1  6  5  2  5  2  2  3  5  4

> apply(table(apples$appleid, apples$TREE), 1, function(x) sum(x>0))
  1   4   5  10  11  13  14  15  17  18  19  25  32  34  36  40  42  48  49  50
  1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1
 51  60  66  67  68  70  72  73  74  76  77  78  83  86  92  93  95  99 100 101
  1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1
111 114 118 120 124 128 129 130 132 135 137 139 142 144 145 149 152 154 159 175
  1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1
177 180 184 187 190 195 196 208 210 212 227 230 233 234 235 242 243 246 247 248
  1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1

> #wrong answer (fits a non-nested model)
> lmer(diam~1+(1|APPLE)+(1|TREE), data=new.apples, method='ML', na.action=na.omit)

> #correct answer for nested levels
> lmer(diam~1+(1|appleid)+(1|TREE), data=new.apples, method='ML', na.action=na.omit)

Course Home Page


Jack Weiss
Phone: (919) 962-5930
E-Mail: jack_weiss@unc.edu
Address: Curriculum in Ecology, Box 3275, University of North Carolina, Chapel Hill, 27516
Copyright © 2006
Last Revised--May 15, 2007
URL: http://www.unc.edu/courses/2006spring/ecol/145/001/docs/lectures/lecture48.htm