Rev 8409 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
### Fit a general linear mixed effects model###### Copyright 2005-2024 The R Core team### Copyright 1997-2003 Jose C. Pinheiro,### Douglas M. Bates <bates@stat.wisc.edu>###### This program is free software; you can redistribute it and/or modify### it under the terms of the GNU General Public License as published by### the Free Software Foundation; either version 2 of the License, or### (at your option) any later version.###### This program is distributed in the hope that it will be useful,### but WITHOUT ANY WARRANTY; without even the implied warranty of### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the### GNU General Public License for more details.###### A copy of the GNU General Public License is available at### http://www.r-project.org/Licenses/lme <-## fits general linear mixed effects model by maximum likelihood, or## residual maximum likelihood using Newton-Raphson algorithm.function(fixed,data = sys.frame(sys.parent()),random,correlation = NULL,weights = NULL,subset,method = c("REML", "ML"),na.action = na.fail,control = list(),contrasts = NULL, keep.data = TRUE)UseMethod("lme")lme.groupedData <-function(fixed,data = sys.frame(sys.parent()),random,correlation = NULL,weights = NULL,subset,method = c("REML", "ML"),na.action = na.fail,control = list(),contrasts = NULL, keep.data = TRUE){args <- as.list(match.call())[-1L]names(args)[1L] <- "data"form <- getResponseFormula(fixed)form[[3]] <- getCovariateFormula(fixed)[[2L]]do.call(lme, c(list(fixed = form), args))}lme.lmList <-function(fixed,data = sys.frame(sys.parent()),random,correlation = NULL,weights = NULL,subset,method = c("REML", "ML"),na.action = na.fail,control = list(),contrasts = NULL, keep.data = TRUE){if (length(grpForm <- getGroupsFormula(fixed, asList = TRUE)) > 1) {stop("can only fit \"lmList\" objects with single grouping variable")}this.call <- as.list(match.call())[-1L]## warn "data" is passed to this functionif (!is.na(match("data", names(this.call)))) {warning("'lme.lmList' will redefine 'data'")}## add object, data, and groups from the call that created objectlast.call <- as.list(attr(fixed, "call"))[-1L]whichLast <- match(c("object", "data", "na.action"), names(last.call))whichLast <- whichLast[!is.na(whichLast)]last.call <- last.call[whichLast]names(last.call)[match(names(last.call), "object")] <- "fixed"this.call[names(last.call)] <- last.callthis.call$fixed <- eval(substitute(L ~ R,list(L = getResponseFormula (fixed)[[2L]],R = getCovariateFormula(fixed)[[2L]])))if (missing(random)) {random <- eval(as.call(this.call[["fixed"]][-2]))}random <- reStruct(random, data = NULL)mData <- this.call[["data"]]if (is.null(mData)) { # will try to constructallV <- all.vars(formula(random))if (length(allV) > 0) {alist <- lapply(as.list(allV), as.name)names(alist) <- allValist <- c(as.list(quote(data.frame)), alist)mode(alist) <- "call"mData <- eval(alist, sys.parent(1))}} else {if (mode(mData) == "name" || mode(mData) == "call") {mData <- eval(mData)}}reSt <- reStruct(random, data = mData) # getting random effects namesnames(reSt) <- names(grpForm)if (length(reSt) > 1) {stop("can only fit \"lmList\" objects with single grouping variable")}rNames <- Names(reSt[[1L]])if (all(match(rNames, names(cf <- na.omit(coef(fixed))), 0))) {if (isInitialized(reSt)) {warning("initial value for \"reStruct\" overwritten in 'lme.lmList'")}madRes <- mad(resid(fixed), na.rm = TRUE)madRan <- unlist(lapply(cf, mad, na.rm = TRUE)[rNames])names(madRan) <- rNamesmatrix(reSt) <- diag((madRan/madRes)^2, ncol = length(rNames))}this.call[["random"]] <- reStval <- do.call(lme.formula, this.call)val$origCall <- match.call()val}lme.formula <-function(fixed,data = sys.frame(sys.parent()),random = pdSymm( eval( as.call(fixed[-2]) ) ),correlation = NULL,weights = NULL,subset,method = c("REML", "ML"),na.action = na.fail,control = list(),contrasts = NULL,keep.data = TRUE){Call <- match.call()miss.data <- missing(data) || !is.data.frame(data)## control parameterscontrolvals <- lmeControl()if (!missing(control)) {controlvals[names(control)] <- control}fixedSigma <- controlvals$sigma > 0## if(fixedSigma && controlvals$apVar) {## if("apVar" %in% names(control))## warning("for 'sigma' fixed, 'apVar' is set FALSE, as the cov approxmation is not yet available.")## controlvals$apVar <- FALSE## }#### checking arguments##if (!inherits(fixed, "formula") || length(fixed) != 3) {stop("fixed-effects model must be a formula of the form \"resp ~ pred\"")}method <- match.arg(method)REML <- method == "REML"reSt <- reStruct(random, REML = REML, data = NULL)groups <- getGroupsFormula(reSt)if (is.null(groups)) {if (inherits(data, "groupedData")) {groups <- getGroupsFormula(data)namGrp <- rev(names(getGroupsFormula(data, asList = TRUE)))Q <- length(namGrp)if (length(reSt) != Q) { # may need to repeat reStif (length(reSt) != 1) {stop("incompatible lengths for 'random' and grouping factors")}randL <- vector("list", Q)names(randL) <- rev(namGrp)for(i in 1:Q) randL[[i]] <- randomreSt <- reStruct(as.list(randL), REML = REML, data = NULL)} else {names(reSt) <- namGrp}} else {## will assume single groupgroups <- ~ 1names(reSt) <- "1"}}## check if corStruct is present and assign groups to its formula,## if necessaryif (!is.null(correlation)) {add.form <- FALSEif(!is.null(corGrpsForm <- getGroupsFormula(correlation, asList = TRUE))) {corGrpsForm <- unlist(lapply(corGrpsForm,function(el) deparse(el[[2L]])))lmeGrpsForm <- unlist(lapply(splitFormula(groups),function(el) deparse(el[[2L]])))corQ <- length(corGrpsForm)lmeQ <- length(lmeGrpsForm)if (corQ <= lmeQ) {if (any(corGrpsForm != lmeGrpsForm[1:corQ])) {stop("incompatible formulas for groups in 'random' and 'correlation'")}if (corQ < lmeQ) {warning("cannot use smaller level of grouping for 'correlation' than for 'random'. Replacing the former with the latter.")add.form <- TRUE}} else if (any(lmeGrpsForm != corGrpsForm[1:lmeQ])) {stop("incompatible formulas for groups in 'random' and 'correlation'")}} else {add.form <- TRUEcorQ <- lmeQ <- 1}if(add.form)## using the same grouping as in randomattr(correlation, "formula") <-eval(substitute(~ COV | GRP,list(COV = getCovariateFormula(formula(correlation))[[2L]],GRP = groups[[2L]])))} else {corQ <- lmeQ <- 1}## create an lme structure containing the random effects model and plug-inslmeSt <- lmeStruct(reStruct = reSt, corStruct = correlation,varStruct = varFunc(weights))## extract a data frame with enough information to evaluate## fixed, groups, reStruct, corStruct, and varStructmfArgs <- list(formula = asOneFormula(formula(lmeSt), fixed, groups),data = data, na.action = na.action)if (!missing(subset)) {mfArgs[["subset"]] <- asOneSidedFormula(Call[["subset"]])[[2L]]}mfArgs$drop.unused.levels <- TRUEdataMix <- do.call(model.frame, mfArgs)origOrder <- row.names(dataMix) # preserve the original orderfor(i in names(contrasts)) # handle contrasts statementcontrasts(dataMix[[i]]) <- contrasts[[i]]## sort the model.frame by groups and get the matrices and parameters## used in the estimation proceduresgrps <- getGroups(dataMix, groups)## ordering data by groupsif (inherits(grps, "factor")) { # single levelord <- order(grps) #"order" treats a single named argument peculiarlygrps <- data.frame(grps)row.names(grps) <- origOrdernames(grps) <- as.character(deparse((groups[[2L]])))} else {ord <- do.call(order, grps)## making group levels uniquefor(i in 2:ncol(grps)) {grps[, i] <-as.factor(paste(as.character(grps[, i-1]),as.character(grps[, i ]), sep = "/"))}}if (corQ > lmeQ) {## may have to reorder by the correlation groupsord <- do.call(order, getGroups(dataMix,getGroupsFormula(correlation)))}grps <- grps[ord, , drop = FALSE]dataMix <- dataMix[ord, ,drop = FALSE]revOrder <- match(origOrder, row.names(dataMix)) # putting in orig. order## obtaining basic model matricesN <- nrow(grps)Z <- model.matrix(reSt, dataMix) # stores contrasts in matrix formncols <- attr(Z, "ncols")Names(lmeSt$reStruct) <- attr(Z, "nams")## keeping the contrasts for later use in predictcontr <- attr(Z, "contr")X <- model.frame(fixed, dataMix)Terms <- attr(X, "terms")if (length(attr(Terms, "offset")))stop("offset() terms are not supported")auxContr <- lapply(X, function(el)if (inherits(el, "factor") &&length(levels(el)) > 1) contrasts(el))contr <- c(contr, auxContr[is.na(match(names(auxContr), names(contr)))])contr <- contr[!unlist(lapply(contr, is.null))]X <- model.matrix(fixed, data=X)y <- eval(fixed[[2L]], dataMix)ncols <- c(ncols, dim(X)[2L], 1)Q <- ncol(grps)## creating the condensed linear modeldims <- MEdims(grps, ncols)attr(lmeSt, "conLin") <-list(Xy = array(c(Z, X, y), c(N, sum(ncols)),list(row.names(dataMix), c(colnames(Z), colnames(X),deparse(fixed[[2L]])))),dims = dims, logLik = 0,## 17-11-2015; Fixed sigma:sigma = controlvals$sigma, auxSigma = 0)## checking if enough observations per group to estimate ranefif(max(dims$ZXlen[[1L]]) < dims$qvec[1L] && !isTRUE(allow <- controlvals$allow.n.lt.q)) {msg <- gettextf("fewer observations than random effects in all level %s groups", Q)if(isFALSE(allow))stop (msg, domain = NA)else # typically NA, was hardwired default in nlme <= 3.1-137 [2018]warning(msg, domain = NA)}## degrees of freedom for testing fixed effectsfixDF <- getFixDF(X, grps, dims$ngrps, terms = Terms)## initializationlmeSt <- Initialize(lmeSt, dataMix, grps, control = controlvals)parMap <- attr(lmeSt, "pmap")## Checking possibility of single decompositionif (length(lmeSt) == 1) { # reStruct only, can do one decomposition## need to save conLin for calculating fitted values and residualsoldConLin <- attr(lmeSt, "conLin")decomp <- TRUEattr(lmeSt, "conLin") <- MEdecomp(attr(lmeSt, "conLin"))} else decomp <- FALSE## Setup for optimization iterationsif(controlvals$opt == "nlminb") {control <- list(iter.max = controlvals$msMaxIter,eval.max = controlvals$msMaxEval,trace = controlvals$msVerbose)keep <- c("abs.tol", "rel.tol", "x.tol", "xf.tol", "step.min","step.max", "sing.tol", "scale.init", "diff.g")} else { ## "optim"control <- list(maxit = controlvals$msMaxIter,reltol = controlvals$msTol,# if(numIter == 0) controlvals$msTol else reltoltrace = controlvals$msVerbose)keep <- c("fnscale", "parscale", "ndeps", "abstol", "alpha", "beta","gamma", "REPORT", "type", "lmm", "factr", "pgtol","temp", "tmax")}control <- c(control, controlvals[names(controlvals) %in% keep])#### getting the linear mixed effects fit object,## possibly iterating for variance functions##numIter <- 0Lrepeat {oldPars <- coef(lmeSt)optRes <-if (controlvals$opt == "nlminb") {nlminb(c(oldPars), function(lmePars) -logLik(lmeSt, lmePars),control = control)} else { ## "optim"if(numIter == 1L) { # (yes, strange, but back-compatible ..) :reltol <- controlvals$reltolif(is.null(reltol)) reltol <- 100*.Machine$double.epscontrol$reltol <- reltol}optim(c(oldPars), function(lmePars) -logLik(lmeSt, lmePars),control = control, method = controlvals$optimMethod)}coef(lmeSt) <- optRes$parattr(lmeSt, "lmeFit") <- MEestimate(lmeSt, grps)## checking if any updating is neededif (!needUpdate(lmeSt)) {if (optRes$convergence) {msg <- gettextf("%s problem, convergence error code = %s\n message = %s",controlvals$opt, optRes$convergence,paste(optRes$message, collapse = ""))if(!controlvals$returnObject)stop(msg, domain = NA)elsewarning(msg, domain = NA)}break}## updating the fit informationnumIter <- numIter + 1LlmeSt <- update(lmeSt, dataMix)## calculating the convergence criterionaConv <- coef(lmeSt)conv <- abs((oldPars - aConv)/ifelse(aConv == 0, 1, aConv))aConv <- NULLfor(i in names(lmeSt)) {if (any(parMap[,i])) {aConv <- c(aConv, max(conv[parMap[,i]]))names(aConv)[length(aConv)] <- i}}if (max(aConv) <= controlvals$tolerance) {break}if (numIter > controlvals$maxIter) {msg <- gettext("maximum number of iterations (lmeControl(maxIter)) reached without convergence")if (controlvals$returnObject) {warning(msg, domain = NA)break} elsestop(msg, domain = NA)}} ## end{repeat}## wrapping uplmeFit <- attr(lmeSt, "lmeFit")names(lmeFit$beta) <- namBeta <- colnames(X)attr(fixDF, "varFixFact") <- varFix <- lmeFit$sigma * lmeFit$varFixvarFix <- crossprod(varFix)dimnames(varFix) <- list(namBeta, namBeta)#### fitted.values and residuals (in original order)##Fitted <- fitted(lmeSt, level = 0:Q,conLin = if (decomp) oldConLin else attr(lmeSt, "conLin"))[revOrder, , drop = FALSE]Resid <- y[revOrder] - Fittedrownames(Resid) <- rownames(Fitted) <- origOrderattr(Resid, "std") <- lmeFit$sigma/(varWeights(lmeSt)[revOrder])## putting groups back in original ordergrps <- grps[revOrder, , drop = FALSE]## making random effects estimates consistently ordered## for(i in names(lmeSt$reStruct)) {## lmeFit$b[[i]] <- lmeFit$b[[i]][unique(as.character(grps[, i])),, drop = F]## NULL## }## inverting back reStructlmeSt$reStruct <- solve(lmeSt$reStruct)## saving part of dimsdims <- attr(lmeSt, "conLin")$dims[c("N", "Q", "qvec", "ngrps", "ncol")]## 17-11-2015; Fixed sigma patch; SH Heisterkamp; Quantitative Solutionsattr(lmeSt, "fixedSigma") <- fixedSigma## getting the approximate var-cov of the parametersapVar <-if (controlvals$apVar) {lmeApVar(lmeSt, lmeFit$sigma,.relStep = controlvals[[".relStep"]],minAbsPar = controlvals[["minAbsParApVar"]],natural = controlvals[["natural"]])} else {"Approximate variance-covariance matrix not available"}## getting rid of condensed linear model and fitattr(lmeSt, "conLin") <- NULLattr(lmeSt, "lmeFit") <- NULLgrpDta <- inherits(data, "groupedData")#### creating the lme object##structure(class = "lme",list(modelStruct = lmeSt,dims = dims,contrasts = contr,coefficients = list(fixed = lmeFit$beta,random = lmeFit$b),varFix = varFix,sigma = lmeFit$sigma,apVar = apVar,logLik = lmeFit$logLik,numIter = if (needUpdate(lmeSt)) numIter, # else NULLgroups = grps,call = Call,terms = Terms,method = method,fitted = Fitted,residuals = Resid,fixDF = fixDF,na.action = attr(dataMix, "na.action"),data = if (keep.data && !miss.data) data),## saving labels and units for plotsunits = if(grpDta) attr(data, "units"),labels= if(grpDta) attr(data, "labels"))}### Auxiliary functions used internally in lme and its methodsgetFixDF <- function(X, grps, ngrps, assign = attr(X, "assign"), terms){## calculates degrees of freedom for fixed effects Wald testsif (!is.list(assign)) { # in RnamTerms <- attr(terms, "term.labels")if (attr(terms, "intercept") > 0) {namTerms <- c("(Intercept)", namTerms)}namTerms <- factor(assign, labels = namTerms)assign <- split(order(assign), namTerms)}## function to check if a vector is (nearly) a multiple of (1,1,...,1)const <- function(x, tolerance = sqrt(.Machine$double.eps)) {if (length(x) < 1) return(NA)x <- as.numeric(x)## returnall(abs(if(x[1L] == 0) x else x/x[1L] - 1) < tolerance)}N <- nrow(X)p <- ncol(X)Q <- ncol(grps)Qp1 <- Q + 1LnamX <- colnames(X)ngrps <- rev(ngrps)[-(1:2)]stratNam <- c(names(ngrps), "Residual")dfX <- dfTerms <- setNames(c(ngrps, N) - c(0, ngrps), stratNam)valX <- setNames(double(p), namX)namTerms <- names(assign)valTerms <- double(length(assign))names(valTerms) <- namTermsif (any(notIntX <- !apply(X, 2, const))) {## percentage of groups for which columns of X are innerinnP <- array(c(rep(1, p),.C(inner_perc_table,as.double(X),as.integer(unlist(grps)),as.integer(p),as.integer(Q),as.integer(N),val = double(p * Q))[["val"]]),dim = c(p, Qp1),dimnames = list(namX, stratNam))## strata in which columns of X are estimated## ignoring fractional inner percentages for nowstratX <- stratNam[apply(innP, 1, function(el, index) max(index[el > 0]),index = 1:Qp1)]## strata in which terms are estimatednotIntTerms <- unlist(lapply(assign,function(el, notIntX) {any(notIntX[el])}, notIntX = notIntX))stratTerms <- stratNam[unlist(lapply(assign,function(el) max(match(stratX[el], stratNam))))][notIntTerms]stratX <- stratX[notIntX]xDF <- table(stratX)dfX[names(xDF)] <- dfX[names(xDF)] - xDFif (!all(notIntX)) { # correcting df for interceptdfX[1L] <- dfX[1L] - 1L} else {dfX[-1L] <- dfX[-1L] + 1L}valX[notIntX] <- dfX[stratX]## number of parameters in each termpTerms <- lengths(assign)[notIntTerms]tDF <- tapply(pTerms, stratTerms, sum)dfTerms[names(tDF)] <- dfTerms[names(tDF)] - tDFif (!all(notIntTerms)) {dfTerms[1L] <- dfTerms[1L] - 1L} else {dfTerms[-1L] <- dfTerms[-1L] + 1L}valTerms[notIntTerms] <- dfTerms[stratTerms]} else {notIntTerms <- vapply(assign, function(el) any(notIntX[el]), NA)}if (!all(notIntX)) { #intercept includedvalX[!notIntX] <- max(dfX)if (!all(notIntTerms))valTerms[!notIntTerms] <- max(dfTerms)}structure(list(X = valX, terms = valTerms),assign = assign)}lmeApVar.fullLmeLogLik <- function(Pars, object, conLin, dims, N, settings) {## logLik as a function of sigma and coef(lmeSt)fixedSigma <- attr(object, "fixedSigma")npar <- length(Pars)if (!fixedSigma) {sigma <- exp(Pars[npar]) # within-group std. dev.Pars <- Pars[-npar]lsigma <- 0} else {sigma <- lsigma <- conLin$sigma}coef(object) <- Parsif ((lO <- length(object)) > 1) {for(i in lO:2)conLin <- recalc(object[[i]], conLin)}val <- .C(mixed_loglik,as.double(conLin$Xy),as.integer(unlist(dims)),as.double(sigma * unlist(pdFactor(solve(object$reStruct)))),as.integer(settings),logLik = double(1L),lRSS = double(1L), sigma=as.double(lsigma))[c("logLik", "lRSS")]aux <- (exp(val[["lRSS"]])/sigma)^2conLin[["logLik"]] + val[["logLik"]] + (N * log(aux) - aux)/2}lmeApVar <-function(lmeSt, sigma, conLin = attr(lmeSt, "conLin"),.relStep = .Machine$double.eps^(1/3), minAbsPar = 0,natural = TRUE){fixedSigma <- attr(lmeSt,"fixedSigma")## calculate approximate variance-covariance matrix of all parameters## except the fixed effects. By default, uses natural parametrization for## for pdSymm matricesdims <- conLin$dimssett <- attr(lmeSt, "settings")N <- dims$N - sett[1L] * dims$ncol[dims$Q + 1L]sett[2:3] <- c(1, 0) # asDelta = TRUE and no grad/HessconLin[["logLik"]] <- 0 # making suresig2 <- sigma * sigmareSt <- lmeSt[["reStruct"]]for(i in seq_along(reSt)) {matrix(reSt[[i]]) <- as.double(sig2) * pdMatrix(reSt[[i]])if (inherits(reSt[[i]], "pdSymm") && natural) {reSt[[i]] <- pdNatural(reSt[[i]])}if (inherits(reSt[[i]], "pdBlocked") && natural) {for(j in seq_along(reSt[[i]])) {if (inherits(reSt[[i]][[j]], "pdSymm")) {reSt[[i]][[j]] <- pdNatural(reSt[[i]][[j]])}}}}lmeSt[["reStruct"]] <- reStcSt <- lmeSt[["corStruct"]]if (!is.null(cSt) && inherits(cSt, "corSymm") && natural) {cStNatPar <- coef(cSt, unconstrained = FALSE)class(cSt) <- c("corNatural", "corStruct")coef(cSt) <- log((cStNatPar + 1)/(1 - cStNatPar))lmeSt[["corStruct"]] <- cSt}Pars <- if(fixedSigma) coef(lmeSt) else c(coef(lmeSt), lSigma = log(sigma))val <- fdHess(Pars, lmeApVar.fullLmeLogLik, lmeSt, conLin, dims, N, sett,.relStep = .relStep, minAbsPar = minAbsPar)[["Hessian"]]if (all(eigen(val, only.values=TRUE)$values < 0)) {## negative definite - OKval <- solve(-val)nP <- names(Pars)dimnames(val) <- list(nP, nP)attr(val, "Pars") <- Parsattr(val, "natural") <- naturalval} else {## problem - solution is not a maximum"Non-positive definite approximate variance-covariance"}}MEdecomp <-function(conLin)## decompose a condensed linear model. Returns another condensed## linear model{dims <- conLin$dimsif (dims[["StrRows"]] >= dims[["ZXrows"]]) {## no point in doing the decompositionreturn(conLin)}dc <- array(.C(mixed_decomp,as.double(conLin$Xy),as.integer(unlist(dims)))[[1L]],c(dims$StrRows, dims$ZXcols))dims$ZXrows <- dims$StrRowsdims$ZXoff <- dims$DecOffdims$ZXlen <- dims$DecLenconLin[c("Xy", "dims")] <- list(Xy = dc, dims = dims)conLin}MEEM <-function(object, conLin, niter = 0)## perform niter iterations of the EM algorithm for conLin## assumes that object is in precision form{if (niter > 0) {dd <- conLin$dimspdCl <- attr(object, "settings")[-(1:3)]pdCl[pdCl == -1] <- 0precvec <- unlist(pdFactor(object))zz <- .C(mixed_EM,as.double(conLin$Xy),as.integer(unlist(dd)),precvec = as.double(precvec),as.integer(niter),as.integer(pdCl),as.integer(attr(object, "settings")[1L]),double(1),double(length(precvec)),double(1),as.double(conLin$sigma))[["precvec"]]Prec <- vector("list", length(object))names(Prec) <- names(object)for (i in seq_along(object)) {len <- dd$qvec[i]^2matrix(object[[i]]) <-crossprod(matrix(zz[1:len + dd$DmOff[i]], ncol = dd$qvec[i]))}}object}MEestimate <-function(object, groups, conLin = attr(object, "conLin")){dd <- conLin$dimsnc <- dd$ncolREML <- attr(object$reStruct, "settings")[1L]Q <- dd$QrConLin <- recalc(object, conLin)zz <- .C(mixed_estimate,as.double(rConLin$Xy),as.integer(unlist(dd)),as.double(unlist(pdFactor(object$reStruct))),as.integer(REML),double(1),estimates = double(dd$StrRows * dd$ZXcols),as.logical(FALSE),## 17-11-2015; Fixed sigma patch; SH Heisterkamp; Quantitative Solutionssigma = as.double(conLin$sigma))[["estimates"]]estimates <- array(zz, c(dd$StrRows, dd$ZXcols))resp <- estimates[ , dd$ZXcols]reSt <- object$reStructnam <- names(reSt)val <- vector(mode = "list", length = Q)start <- dd$StrRows * c(0, cumsum(nc))for (i in seq_along(reSt)) {val[[i]] <-matrix(resp[as.vector(outer(1:(nc[i]), dd$SToff[[i]] - start[i], "+"))],ncol = nc[i], byrow = TRUE,dimnames = list(unique(as.character(groups[, nam[i]])),Names(reSt[[i]])))}names(val) <- namp <- nc[[Q + 1L]]N <- dd$N - REML * pdimE <- dim(estimates)## 17-11-2015; Fixed sigma patch; ... modified by MM notably for p == 0:Np <- NauxSigma <- abs(resp[dimE[1]])/sqrt(Np)if(conLin$sigma > 0) {loglik <- (N * (-log(2 * pi)-2*log(conLin$sigma)))/2 + rConLin$logLiksigma <- conLin$sigma} else {loglik <- (N * (log(N) - (1 + log(2 * pi))))/2 + rConLin$logLiksigma <- auxSigma}list(logLik = loglik,b = rev(val),beta = if(p) resp[dimE[1] - (p:1)] else double(),sigma = sigma,auxSigma = auxSigma,varFix = if(p)t(solve(estimates[dimE[1] - (p:1), dimE[2] - (p:1), drop = FALSE]))elsematrix(,p,p))}MEdims <- function(groups, ncols){## define constants used in matrix decompositions and log-lik calculations## first need some local functionsglengths <-## returns the group lengths from a vector of last rows in the groupfunction(lstrow) diff(c(0, lstrow))offsets <-## converts total number of columns(N), columns per level(ncols), and## a list of group lengths to offsets in C arraysfunction(N, ncols, lstrow, triangle = FALSE){pop <- function(x) x[-length(x)]cstart <- c(0, cumsum(N * ncols))for (i in seq_along(lstrow)) {lstrow[[i]] <- cstart[i] +if (triangle) {lstrow[[i]] - ncols[i] # storage offsets style} else {pop(c(0, lstrow[[i]])) # decomposition style}}lstrow}Q <- ncol(groups) # number of levelsN <- nrow(groups) # number of observations## 'isLast' indicates if the row is the last row in the group at that level.## this version propagates changes from outer groups to inner groups## isLast <- (array(unlist(lapply(c(rev(as.list(groups)),## list(X = rep(0, N), y = rep(0, N))),## function(x) c(0 != diff(codes(x)), TRUE))),## c(N, Q+2), list(NULL, c(rev(names(groups)), "X", "y")))## %*% (row(diag(Q+2)) >= col(diag(Q+2)))) != 0## this version does not propagate changes from outer to inner.isLast <- array(FALSE, dim(groups) + c(0, 2),list(NULL, c(rev(names(groups)), "X", "y")))for(i in 1:Q) {isLast[, Q + 1L - i] <- c(0 != diff(as.integer(groups[[i]])), TRUE)}isLast[N, ] <- TRUElastRow <- apply(isLast, 2, function(x) seq_along(x)[x])if(!is.list(lastRow)) {nm <- names(lastRow)lastRow <- as.list(lastRow)names(lastRow) <- nm}isLast <- t(isLast)strSizes <- cumsum(ncols * isLast) * isLast # required storage sizeslastStr <- apply(t(strSizes), 2, function(x) x[x != 0])if(!is.list(lastStr)) {nm <- names(lastStr)lastStr <- as.list(lastStr)names(lastStr) <- nm}strRows <- max(lastStr[[length(lastStr)]])lastBlock <- vector("list", Q)names(lastBlock) <- rownames(strSizes)[1:Q]for(i in 1:Q) lastBlock[[i]] <- c(strSizes[i, -N], strRows)maxStr <- do.call(pmax, lastBlock)for(i in 1:Q) lastBlock[[i]] <- maxStr[as.logical(lastBlock[[i]])]lastBlock <- c(lastBlock, list(X = strRows, y = strRows))list(N = N, # total number of rows in dataZXrows = N, # no. of rows in arrayZXcols = sum(ncols), # no. of columns in arrayQ = Q, # no. of levels of random effectsStrRows = strRows, # no. of rows required for storageqvec = ncols * c(rep(1, Q), 0, 0), # lengths of random effectsngrps = lengths(lastRow),# no. of groups at each level and 1s for X, yDmOff = c(0, cumsum(ncols^2))[1:(Q+2)],# offsets into DmHalf array by levelncol = ncols, # no. of columns decomposed per levelnrot = rev(c(0, cumsum(rev(ncols))))[-1L],# no. of columns rotated per levelZXoff = offsets(N, ncols, lastRow), # offsets into ZXyZXlen = lapply(lastRow, glengths), # lengths of ZXy groups# storage array offsetsSToff = offsets(strRows, ncols, lastStr, triangle = TRUE),# decomposition offsetsDecOff = offsets(strRows, ncols, lastBlock),# decomposition lengthsDecLen = lapply(lastBlock, glengths))}### Methods for standard genericsACF.lme <-function(object, maxLag,resType = c("pearson", "response", "normalized"), ...){resType <- match.arg(resType)res <- resid(object, type = resType, asList = TRUE)if(missing(maxLag)) {maxLag <- min(c(maxL <- max(lengths(res)) - 1,as.integer(10 * log10(maxL + 1))))}val <- lapply(res,function(el, maxLag) {N <- maxLag + 1Ltt <- double(N)nn <- integer(N)N <- min(c(N, n <- length(el)))nn[1:N] <- n + 1L - 1:N## el <- el - mean(el)for(i in 1:N) {tt[i] <- sum(el[1:(n-i+1)] * el[i:n])}array(c(tt,nn), c(length(tt), 2))}, maxLag = maxLag)val0 <- rowSums(sapply(val, function(x) x[,2]))val1 <- rowSums(sapply(val, function(x) x[,1]))/val0val2 <- val1/val1[1L]z <- data.frame(lag = 0:maxLag, ACF = val2)attr(z, "n.used") <- val0class(z) <- c("ACF", "data.frame")z}anova.lme <-function(object, ..., test = TRUE, type = c("sequential", "marginal"),adjustSigma = TRUE, Terms, L, verbose = FALSE){fixSig <- attr(object$modelStruct, "fixedSigma")fixSig <- !is.null(fixSig) && fixSig## returns the likelihood ratio statistics, the AIC, and the BICLmiss <- missing(L)if ((rt <- ...length() + 1L) == 1L) { ## just one objectif (!inherits(object,"lme")) {stop(gettextf("object must inherit from class %s", '"lme"'), domain = NA)}vFix <- attr(object$fixDF, "varFixFact")if (adjustSigma && object$method == "ML")## using REML-like estimate of sigma under MLvFix <- sqrt(object$dims$N/(object$dims$N - ncol(vFix))) * vFixc0 <- solve(t(vFix), fixef(object))assign <- attr(object$fixDF, "assign")nTerms <- length(assign)if (missing(Terms) && Lmiss) {## returns the F.table (Wald) for the fixed effectstype <- match.arg(type)Fval <- Pval <- double(nTerms)nDF <- integer(nTerms)dDF <- object$fixDF$termsfor(i in 1:nTerms) {nDF[i] <- length(assign[[i]])if (type == "sequential") { # type I SSc0i <- c0[assign[[i]]]} else {c0i <- c(qr.qty(qr(vFix[, assign[[i]], drop = FALSE]), c0))[1:nDF[i]]}Fval[i] <- sum(c0i^2)/nDF[i]Pval[i] <- 1 - pf(Fval[i], nDF[i], dDF[i])}#### fixed effects F-values, df, and p-values##aod <- data.frame(numDF= nDF, denDF= dDF, "F-value"= Fval, "p-value"= Pval,check.names = FALSE)rownames(aod) <- names(assign)attr(aod,"rt") <- rt} else {nX <- length(unlist(assign))if (Lmiss) { # terms is givenif (is.numeric(Terms) && all(Terms == as.integer(Terms))) {if (min(Terms) < 1 || max(Terms) > nTerms) {stop(gettextf("'Terms' must be between 1 and %d", nTerms),domain = NA)}} else {if (is.character(Terms)) {if (any(noMatch <- is.na(match(Terms, names(assign))))) {stop(sprintf(ngettext(sum(noMatch),"term %s not matched","terms %s not matched"),paste(Terms[noMatch], collapse = ", ")),domain = NA)}} else {stop("terms can only be integers or characters")}}dDF <- unique(object$fixDF$terms[Terms])if (length(dDF) > 1) {stop("terms must all have the same denominator DF")}lab <-paste("F-test for:",paste(names(assign[Terms]),collapse=", "),"\n")L <- diag(nX)[unlist(assign[Terms]),,drop=FALSE]} else {L <- as.matrix(L)if (ncol(L) == 1) L <- t(L) # single linear combinationnrowL <- nrow(L)ncolL <- ncol(L)if (ncol(L) > nX) {stop(sprintf(ngettext(nX,"'L' must have at most %d column","'L' must have at most %d columns"),nX), domain = NA)}dmsL1 <- rownames(L)L0 <- array(0, c(nrowL, nX), list(NULL, names(object$fixDF$X)))if (is.null(dmsL2 <- colnames(L))) {## assume same order as effectsL0[, 1:ncolL] <- L} else {if (any(noMatch <- is.na(match(dmsL2, colnames(L0))))) {stop(sprintf(ngettext(sum(noMatch),"effect %s not matched","effects %s not matched"),paste(dmsL2[noMatch],collapse=", ")),domain = NA)}L0[, dmsL2] <- L}L <- L0[noZeroRowL <- as.logical((L0 != 0) %*% rep(1, nX)), , drop = FALSE]nrowL <- nrow(L)rownames(L) <- if(is.null(dmsL1)) 1:nrowL else dmsL1[noZeroRowL]dDF <-unique(object$fixDF$X[noZeroColL <-as.logical(c(rep(1,nrowL) %*% (L != 0)))])if (length(dDF) > 1) {stop("L may only involve fixed effects with the same denominator DF")}lab <- "F-test for linear combination(s)\n"}nDF <- sum(svd.d(L) > 0)c0 <- c(qr.qty(qr(vFix %*% t(L)), c0))[1:nDF]Fval <- sum(c0^2)/nDFPval <- pf(Fval, nDF, dDF, lower.tail=FALSE)aod <- data.frame(numDF = nDF, denDF = dDF, "F-value" = Fval, "p-value" = Pval,check.names=FALSE)attr(aod, "rt") <- rtattr(aod, "label") <- labif (!Lmiss) {attr(aod, "L") <-if(nrow(L) > 1) L[, noZeroColL, drop = FALSE] else L[, noZeroColL]}}}#### Otherwise construct the likelihood ratio and information table## objects in ... may inherit from gls, gnls, lm, lmList, lme,## nlme, nlsList, and nls##else {ancall <- sys.call() # yuck.. hackancall$verbose <- ancall$test <- ancall$type <- NULLobject <- list(object, ...)valid.cl <- c("gls", "gnls", "lm", "lmList", "lme","nlme","nlsList","nls")if (!all(vapply(object, inherits, TRUE, what = valid.cl))) {valid.cl <- paste0('"', valid.cl, '"')stop(gettextf("objects must inherit from classes %s, or %s",paste(head(valid.cl, -1), collapse=", "), tail(valid.cl, 1)),domain=NA)}resp <- vapply(object,function(el) deparse(getResponseFormula(el)[[2L]]), "")## checking if responses are the samesubs <- as.logical(match(resp, resp[1L], FALSE))if (!all(subs))warning("some fitted objects deleted because response differs from the first model")if (sum(subs) == 1)stop("first model has a different response from the rest")object <- object[subs]rt <- length(object)termsModel <- lapply(object, function(el) formula(el)[-2])estMeth <- vapply(object, function(el)if (is.null(val <- el[["method"]])) NA_character_ else val, "")## checking consistency of estimation methodsif(length(uEst <- unique(estMeth[!is.na(estMeth)])) > 1) {stop("all fitted objects must have the same estimation method")}estMeth[is.na(estMeth)] <- uEst## checking if all models have same fixed effects when estMeth = "REML"REML <- uEst == "REML"if(REML) {aux <- vapply(termsModel,function(el) {tt <- terms(el)val <- paste(sort(attr(tt, "term.labels")), collapse = "&")if (attr(tt, "intercept") == 1)paste(val, "(Intercept)", sep = "&") else val}, ".")if(length(unique(aux)) > 1) {warning("fitted objects with different fixed effects. REML comparisons are not meaningful.")}}termsCall <-lapply(object, function(el) {if (is.null(val <- el$call) &&is.null(val <- attr(el, "call")))stop("objects must have a \"call\" component or attribute")val})termsCall <- vapply(termsCall,function(el) paste(deparse(el), collapse =""), "")aux <- lapply(object, logLik, REML)if (length(unique(vapply(aux, attr, 1, "nall"))) > 1) {stop("all fitted objects must use the same number of observations")}dfModel <- vapply(aux, attr, 1, "df")logLik <- vapply(aux, c, 1.1)aod <- data.frame(call = termsCall,Model = 1:rt,df = dfModel,AIC = vapply(aux, AIC, 1.),BIC = vapply(aux, BIC, 1.),logLik = logLik,check.names = FALSE)if (test) {ddf <- diff(dfModel)if (sum(abs(ddf)) > 0) {effects <- rep("", rt)for(i in 2:rt) {if (ddf[i-1] != 0) {effects[i] <- paste(i - 1, i, sep = " vs ")}}pval <- rep(NA, rt - 1)ldf <- as.logical(ddf)lratio <- 2 * abs(diff(logLik))lratio[!ldf] <- NApval[ldf] <- pchisq(lratio[ldf], abs(ddf[ldf]), lower.tail=FALSE)aod <- data.frame(aod,Test = effects,"L.Ratio" = c(NA, lratio),"p-value" = c(NA, pval),check.names = FALSE,stringsAsFactors = TRUE)}}row.names(aod) <- vapply(as.list(ancall[-1L]), c_deparse, "")attr(aod, "rt") <- rtattr(aod, "verbose") <- verbose}class(aod) <- c("anova.lme", "data.frame")aod}## (This is "cut'n'paste" similar to augPred.gls() in ./gls.R -- keep in sync!)augPred.lme <-function(object, primary = NULL, minimum = min(primary),maximum = max(primary), length.out = 51L, level = Q, ...){data <- eval.parent(object$call$data)if (!inherits(data, "data.frame")) {stop(gettextf("data in %s call must evaluate to a data frame",sQuote(substitute(object))), domain = NA)}if(is.null(primary)) {if (!inherits(data, "groupedData")) {stop(gettextf("%s without \"primary\" can only be used with fits of \"groupedData\" objects",sys.call()[[1L]]), domain = NA)}primary <- getCovariate(data)pr.var <- getCovariateFormula(data)[[2L]]} else{pr.var <- asOneSidedFormula(primary)[[2L]]primary <- eval(pr.var, data)}prName <- c_deparse(pr.var)newprimary <- seq(from = minimum, to = maximum, length.out = length.out)Q <- object$dims$Q # number of levelsif (is.null(level)) level <- QnL <- length(level) # number of requested levelsmaxLev <- max(c(level, 1))groups <- getGroups(object, level = maxLev)if (!is.ordered(groups)) {groups <- ordered(groups, levels = unique(as.character(groups)))}grName <- ".groups"ugroups <- unique(groups)value <- data.frame(rep(rep(newprimary, length(ugroups)), nL),rep(rep(ugroups, rep(length(newprimary),length(ugroups))), nL))names(value) <- c(prName, grName)## recovering other variables in data that may be needed for predictions## varying variables will be replaced by their meanssummData <- gsummary(data, groups = groups)if (any(toAdd <- is.na(match(names(summData), names(value))))) {summData <- summData[, toAdd, drop = FALSE]}value[, names(summData)] <- summData[value[, 2L], ]pred <- predict(object, value[seq_len(nrow(value)/nL), , drop = FALSE],level = level)if (nL > 1) { # multiple levelspred <- pred[, ncol(pred) - (nL - 1):0] # eliminating groupspredNames <- rep(names(pred), rep(nrow(pred), nL))pred <- c(unlist(pred))} else {predNames <- rep("predicted", nrow(value))}newvals <- cbind(value[, 1:2], pred)names(newvals)[3] <- respName <-deparse(resp.var <- getResponseFormula(object)[[2L]])orig <- data.frame(primary, groups, getResponse(object))names(orig) <- names(newvals)value <- rbind(orig, newvals)attributes(value[, 2]) <- attributes(groups)value[, ".type"] <- ordered(c(rep("original", nrow(data)), predNames),levels = c(unique(predNames), "original"))labs <- list(x = prName, y = respName)unts <- list(x = "", y = "")if(inherits(data, "groupedData")) {labs[names(attr(data, "labels"))] <- attr(data, "labels")unts[names(attr(data, "units"))] <- attr(data, "units")attr(value, "units") <- attr(data, "units")}structure(value, class = c("augPred", class(value)),labels = labs,units = unts,formula= eval(substitute(Y ~ X | G,list(Y = resp.var, X = pr.var,G = as.name(grName)))))}coef.lme <-function(object, augFrame = FALSE, level = Q, data, which = 1:ncol(data),FUN = mean, omitGroupingFactor = TRUE, subset = NULL, ...){Q <- object$dims$Qif (length(level) > 1) {stop("only single level allowed")}fixed <- fixef(object)p <- length(fixed)value <- ranef(object, level = 1:level)grps <- object[["groups"]]if (Q > 1) {grpNames <- t(array(rep(rev(names(grps)), Q), c(Q, Q)))grpNames[lower.tri(grpNames)] <- ""grpNames <-rev(apply(grpNames, 1,function(x) paste(x[x != ""], collapse = " %in% ")))[level]} else {grpNames <- names(grps)}grps <- grps[, 1:level, drop = FALSE]grps <- gsummary(grps, groups = grps[, level])if (level == 1) value <- list(value)effNams <- unlist(lapply(value, names))grps <- grps[row.names(value[[level]]), , drop = FALSE]M <- nrow(grps)effNams <- unique(c(names(fixed), effNams))effs <- array(0, c(M, length(effNams)),list(row.names(grps), effNams))effs[, names(fixed)] <- array(rep(fixed, rep(M, p)), c(M, p))for (i in 1:level) {nami <- names(value[[i]])effs[, nami] <- as.matrix(effs[, nami] + value[[i]][as.character(grps[, i]), ])}if (augFrame) { # can only do that for last levelif (missing(data)) {data <- getData(object)}data <- as.data.frame(data)data <- data[, which, drop = FALSE]value <- ranef(object, TRUE, level, data, FUN = FUN,omitGroupingFactor = omitGroupingFactor,subset = subset)whichKeep <- is.na(match(names(value), effNams))if (any(whichKeep)) {effs <- cbind(effs, value[, whichKeep, drop = FALSE])}}effs <- as.data.frame(effs)attr(effs, "level") <- levelattr(effs, "label") <- "Coefficients"attr(effs, "effectNames") <- effNamsattr(effs, "standardized") <- FALSEattr(effs, "grpNames") <- grpNamesclass(effs) <- unique(c("coef.lme", "ranef.lme", class(effs)))effs}fitted.lme <-function(object, level = Q, asList = FALSE, ...){Q <- object$dims$Qval <- object[["fitted"]]if (is.character(level)) { # levels must be given consistentlynlevel <- match(level, names(val))if (any(aux <- is.na(nlevel))) {stop(sprintf(ngettext(sum(aux),"nonexistent level %s","nonexistent levels %s"),level[aux]), domain = NA)}level <- nlevel} else { # assuming integerslevel <- 1 + level}if (length(level) == 1L) {grp.nm <- row.names(object[["groups"]])grps <- as.character(object[["groups"]][, max(c(1, level - 1))])if (asList) {val <- as.list(split(val, ordered(grps, levels = unique(grps))))} else {val <- napredict(object$na.action, val[, level])names(val) <- grps[match(names(val), grp.nm)]}lab <- "Fitted values"if (!is.null(aux <- attr(object, "units")$y))lab <- paste(lab, aux)attr(val, "label") <- labval} else napredict(object$na.action, val[, level])}formula.lme <- function(x, ...) formula(x$terms)fixef.lme <- function(object, ...) object$coefficients$fixedgetGroups.lme <- function(object, form, level = Q, data, sep){Q <- object$dims$Qval <- object[["groups"]][, level]if (length(level) == 1) { # single groupattr(val, "label") <- names(object[["groups"]])[level]}val}getGroupsFormula.lme <-function(object, asList = FALSE, sep){getGroupsFormula(object$modelStruct$reStruct, asList)}getResponse.lme <-function(object, form){val <- resid(object) + fitted(object)if (is.null(lab <- attr(object, "labels")$y)) {lab <- deparse(getResponseFormula(object)[[2L]])}if (!is.null(aux <- attr(object, "units")$y)) {lab <- paste(lab, aux)}attr(val, "label") <- labval}intervals.lme <-function(object, level = 0.95, which = c("all", "var-cov", "fixed"), ...){which <- match.arg(which)val <- list()## 17-11-2015; Fixed sigma patch; SH Heisterkamp; Quantitative SolutionsfixSig <- attr(object$modelStruct, "fixedSigma")fixSig <- !is.null(fixSig) && fixSigif (which != "var-cov") { # fixed effects includedest <- fixef(object)len <- -qt((1-level)/2, object$fixDF$X) * sqrt(diag(object$varFix))vfix <- array(c(est - len, est, est + len), c(length(est), 3),list(names(est), c("lower", "est.", "upper")))attr(vfix, "label") <- "Fixed effects:"val <- list(fixed = vfix)}if (which != "fixed") { # variance-covariance includedif (is.character(aV <- object$apVar)) {stop(gettextf("cannot get confidence intervals on var-cov components: %s\n Consider '%s'",aV, "which = \"fixed\""), domain = NA)}est <- attr(aV, "Pars")nP <- length(est)len <- -qnorm((1-level)/2) * sqrt(diag(aV))origInt <- # intervals in unconstrained parametersarray(c(est - len, est, est + len),c(nP, 3), list(names(est), c("lower", "est.", "upper")))lmeSt <- object$modelStructif (!all(whichKeep <- apply(attr(lmeSt, "pmap"), 2, any))) {## need to deleted components with fixed coefficientsaux <- lmeSt[whichKeep]class(aux) <- class(lmeSt)attr(aux, "settings") <- attr(lmeSt, "settings")attr(aux, "pmap") <- attr(lmeSt, "pmap")[, whichKeep, drop = FALSE]lmeSt <- aux}cSt <- lmeSt[["corStruct"]]if (!is.null(cSt) && inherits(cSt, "corSymm") && attr(aV, "natural")) {## converting to corNaturalclass(cSt) <- c("corNatural", "corStruct")lmeSt[["corStruct"]] <- cSt}pmap <- attr(lmeSt, "pmap")namL <- names(lmeSt)## 17-11-2015; Fixed sigma patch; SH Heisterkamp; Quantitative Solutionsif (fixSig) {natInt <- vector("list", length(namL))names(natInt) <- namL} else {natInt <- vector("list", length(namL) + 1)names(natInt) <- c(namL, "sigma") # list of intervals in natural pars## intervals for sigma are stored separately and dropped from origIntvsig <- exp(origInt[nP, ])attr(vsig, "label") <- "Within-group standard error:"natInt[["sigma"]] <- vsigorigInt <- origInt[ - nP,, drop = FALSE]}if (attr(aV, "natural")) { # convert any pdSymm's to pdNatural'sfor(i in seq_along(lmeSt$reStruct)) {if (inherits(s.i <- lmeSt$reStruct[[i]], "pdSymm")) {s.i <- pdNatural(s.i)} else if (inherits(s.i, "pdBlocked")) {for(j in seq_along(s.i))if (inherits(s.i[[j]], "pdSymm"))s.i[[j]] <- pdNatural(s.i[[j]])}lmeSt$reStruct[[i]] <- s.i}}rownames(origInt) <- # re-express names if necessary## namP <-names(coef(lmeSt, unconstrained = FALSE))for(i in 1:3) { # re-express intervals in constrained parscoef(lmeSt) <- origInt[,i]origInt[,i] <- coef(lmeSt, unconstrained = FALSE)}for(i in namL) {natInt[[i]] <- origInt[ pmap[ , i ], , drop = FALSE ]switch(i,"reStruct" = {plen <- attr( lmeSt$reStruct, "plen" )natInt[[i]] <-rev(as.matrix( split( as.data.frame( natInt[[i]] ),rep( seq_along(plen), plen ))))names(natInt[[i]]) <- rev(names(plen))for (j in names(plen)) {dimnames(natInt[[i]][[j]])[[1L]] <-names( coef( lmeSt[[i]][[j]], unconstrained = FALSE ) )}},"corStruct" =,"varStruct" = {dimnames(natInt[[i]])[[1L]] <-names(coef(lmeSt[[i]], unconstrained = FALSE))})attr(natInt[[i]], "label") <-switch(i,reStruct = "Random Effects:",corStruct = "Correlation structure:",varStruct = "Variance function:",paste0(i,":"))}val <- c(val, natInt)}attr(val, "level") <- levelclass(val) <- "intervals.lme"val}logLik.lme <- function(object, REML, ...){## 17-11-2015; Fixed sigma patch; SH Heisterkamp; Quantitative SolutionsfixSig <- attr(object[["modelStruct"]], "fixedSigma")fixSig <- !is.null(fixSig) && fixSigod <- object$dimsp <- od$ncol[[od$Q + 1L]]N <- od$N## Np <- N - pestM <- object$methodif (missing(REML)) REML <- estM == "REML"val <- object[["logLik"]]if (REML && (estM == "ML")) { # have to correct logLikval <- val + (p * (log(2 * pi) + 1L) + (N - p) * log(1 - p/N) +sum(log(abs(svd.d(object$varFix))))) / 2}if (!REML && (estM == "REML")) { # have to correct logLikval <- val - (p * (log(2*pi) + 1L) + N * log(1 - p/N) +sum(log(abs(svd.d(object$varFix))))) / 2}structure(val, class = "logLik",nall = N,nobs = N - REML * p,## 17-11-2015; Fixed sigma patch; SH Heisterkamp; Quantitative Solutionsdf = p + length(coef(object[["modelStruct"]])) + as.integer(!fixSig))}nobs.lme <- function(object, ...) object$dims$Npairs.lme <-function(x, form = ~coef(.), label, id = NULL, idLabels = NULL,grid = FALSE, ...){object <- x## scatter plot matrix plots, generally based on coef or ranefif (!inherits(form, "formula")) {stop("'form' must be a formula")}if (length(form) != 2) {stop("'form' must be a one-sided formula")}## constructing dataallV <- all.vars(asOneFormula(form, id, idLabels))allV <- allV[is.na(match(allV,c("T","F","TRUE","FALSE")))]if (length(allV) > 0) {data <- getData(object)if (is.null(data)) { # try to construct dataalist <- lapply(as.list(allV), as.name)names(alist) <- allValist <- c(as.list(quote(data.frame)), alist)mode(alist) <- "call"data <- eval(alist, sys.parent(1))} else {if (any(naV <- is.na(match(allV, names(data))))) {stop(sprintf(ngettext(sum(naV),"%s not found in data","%s not found in data"),allV[naV]), domain = NA)}}} else data <- NULL## argument listdots <- list(...)args <- if(length(dots) > 0) dots else list()## covariate - must be present as a data.framecovF <- getCovariateFormula(form).x <- eval(covF[[2L]], list(. = object)) # only function of "."if (!inherits(.x, "data.frame")) {stop("covariate must be a data frame")}level <- attr(.x, "level")if (!is.null(effNams <- attr(.x, "effectNames"))) {.x <- .x[, effNams, drop = FALSE]}## eliminating constant effectsisFixed <- vapply(.x, function(el) length(unique(el)) == 1L, NA).x <- .x[, !isFixed, drop = FALSE]nc <- ncol(.x)if (nc == 1) {stop("cannot do pairs of just one variable")}if (!missing(label)) {names(.x) <- label}if (nc == 2) {## will use xyplotargForm <- .y ~ .xargData <- .xnames(argData) <- c(".x", ".y")if (is.null(args$xlab)) args$xlab <- names(.x)[1L]if (is.null(args$ylab)) args$ylab <- names(.x)[2L]} else { # splomargForm <- ~ .xargData <- list(.x = .x)}auxData <- list()## groups - need not be presentgrpsF <- getGroupsFormula(form)if (!is.null(grpsF)) {gr <- splitFormula(grpsF, sep = "*")for(i in seq_along(gr)) {for(j in all.vars(gr[[i]])) {auxData[[j]] <- eval(as.name(j), data)}}argForm <- eval(substitute(if(length(argForm) == 2) ~ .x | R else .y ~ .x | R,list(R = grpsF[[2L]])))}## id and idLabels - need not be presentif (!is.null(id)) { # identify points in plotN <- object$dims$Nid <-switch(mode(id),numeric = {if ((id <= 0) || (id >= 1)) {stop("'id' must be between 0 and 1")}if (is.null(level)) {stop("covariate must have a level attribute when groups are present")}aux <- t(as.matrix(ranef(object, level = level)))aux <- as.logical(colSums((solve(t(pdMatrix(object$modelStruct$reStruct, factor = TRUE)[[level]]),aux)/object$sigma)^2) > qchisq(1 - id, dim(aux)[1L]))aux},call = eval(asOneSidedFormula(id)[[2L]], data),stop("'id' can only be a formula or numeric"))if (length(id) == N) {## id as a formula evaluated in dataif (is.null(level)) {stop("covariate must have a level attribute when 'id' is a formula")}auxData[[".id"]] <- id}if (is.null(idLabels)) {idLabels <- row.names(.x)} else {if (mode(idLabels) == "call") {idLabels <-as.character(eval(asOneSidedFormula(idLabels)[[2L]], data))} else if (is.vector(idLabels)) {if (length(idLabels <- unlist(idLabels)) != N) {stop("'idLabels' of incorrect length")}idLabels <- as.character(idLabels)} else {stop("'idLabels' can only be a formula or a vector")}}if (length(idLabels) == N) {## idLabels as a formula evaluated in dataif (is.null(level)) {stop("covariate must have a level attribute when 'idLabels' is a formula")}auxData[[".Lid"]] <- idLabels}}if (length(auxData)) { # need collapsingauxData <- gsummary(as.data.frame(auxData),groups = getGroups(object, level = level))auxData <- auxData[row.names(.x), , drop = FALSE]if (!is.null(auxData[[".id"]])) {id <- auxData[[".id"]]}if (!is.null(auxData[[".Lid"]])) {idLabels <- auxData[[".Lid"]]}wchDat <- is.na(match(names(auxData), c(".id", ".idLabels")))if (any(wchDat)) {argData <- c(argData, as.list(auxData[, wchDat, drop = FALSE]))}}if (!is.null(id)) id <- as.logical(as.character(id))idLabels <- as.character(idLabels)## adding to args listargs <- c(list(argForm, data = argData), args)if (is.null(args$strip)) {args$strip <- function(...) strip.default(..., style = 1)}if (is.null(args$cex)) args$cex <- par("cex")if (is.null(args$adj)) args$adj <- par("adj")## defining the type of plotif (length(argForm) == 3) { # xyplotplotFun <- "xyplot"if(is.null(args$panel))args$panel <- function(x, y, subscripts, ...) {x <- as.numeric(x)y <- as.numeric(y)dots <- list(...)if (grid) panel.grid()panel.xyplot(x, y, ...)if (any(ids <- id[subscripts])){ltext(x[ids], y[ids], idLabels[subscripts][ids],cex = dots$cex, adj = dots$adj)}}} else { # splomplotFun <- "splom"if(is.null(args$panel)) {args$panel <- function(x, y, subscripts, ...) {x <- as.numeric(x)y <- as.numeric(y)dots <- list(...)if (grid) panel.grid()panel.xyplot(x, y, ...)if (any(ids <- id[subscripts])){ltext(x[ids], y[ids], idLabels[subscripts][ids],cex = dots$cex, adj = dots$adj)}}}}do.call(plotFun, as.list(args))}plot.ranef.lme <-function(x, form = NULL, omitFixed = TRUE, level = Q,grid = TRUE, control,xlab = NULL, ylab = NULL, strip = NULL, ...){plotControl <-function(drawLine = TRUE, span.loess = 2/3, degree.loess = 1) {list(drawLine = drawLine,span.loess = span.loess,degree.loess = degree.loess)}pControl <- plotControl()if (!missing(control)) pControl[names(control)] <- controlif (!inherits(x, "data.frame")) {## must be a list of data framesQ <- length(x) # the default for 'level'if (length(level) > 1) {stop("only single level allowed")}oAttr <- attributes(x)[c("label", "standardized", "namsEff")]x <- x[[level]]oAttr$namsEff <- oAttr$namsEff[level]attributes(x)[c("label", "standardized", "namsEff")] <- oAttr}if (omitFixed) { # eliminating constant effectsisFixed <- vapply(x, function(el) length(unique(el)) == 1L, NA)if (any(isFixed)) {oattr <- attributes(x)oattr <- oattr[names(oattr) != "names"]x <- x[, !isFixed, drop = FALSE]oattr$effectNames <- oattr$effectNames[!is.na(match(oattr$effectNames,names(x)))]attributes(x)[names(oattr)] <- oattr}}eNames <- attr(x, "effectNames")if (is.null(form) || (inherits(form, "formula") && length(form) == 2)) {## ~ x : dotploteLen <- length(eNames)argData <- data.frame(.pars = as.vector(unlist(x[, eNames])),.enames = ordered(rep(eNames, rep(nrow(x), eLen)),levels = eNames), check.names = FALSE)for(i in names(x)[is.na(match(names(x), eNames))]) {argData[[i]] <- rep(x[[i]], eLen)}argForm <- .groups ~ .pars | .enamesargData[[".groups"]] <- rep(row.names(x), eLen)if (inherits(form, "formula")) {onames <- all.vars(form)if (any(whichNA <- is.na(match(onames, names(argData))))) {stop(sprintf(ngettext(sum(whichNA),"%s not available for plotting","%s not available for plotting"),onames[whichNA], collapse = ", "), domain = NA)}argData[[".groups"]] <-as.character(argData[[as.character(onames[1L])]])if (length(onames) > 1) {for(i in onames[-1L]) {argData[[".groups"]] <-paste(as.character(argData[[".groups"]]),as.character(argData[[i]]))}}}argData[[".groups"]] <- ordered(argData[[".groups"]],levels = unique(argData[[".groups"]]))args <- list(argForm, data = argData, ...)args$xlab <- xlab %||% attr(x, "label")args$ylab <- ylab %||% if (is.null(form)) attr(x, "grpNames")else deparse(form[[2L]])if (is.null(args$scales)) {if (!is.null(attr(x, "standardized")) &&!attr(x, "standardized")) {args$scales <- list(x = list(relation = "free"))}}args$strip <- strip %||% function(...) strip.default(..., style = 1)do.call(dotplot, args)} else { ## y ~ x ---> xyplot(): ------------------------------------------if (!inherits(form, "formula")) stop("'form' must be a formula when not NULL")reName <- form[[2L]]if (length(reName) != 1 &&substring(deparse(reName),nchar(deparse(reName), "c") - 10) != "(Intercept)") {stop("only single effects allowed in left side of 'form'")}reName <- deparse(reName)if (is.na(match(reName, eNames))) {stop(gettextf("%s is not a valid effect name", sQuote(reName)),domain = NA)}vNames <- all.vars(form[[3]]) # variable namesif (any(!is.na(match(vNames, eNames)))) {stop("no effects allowed in right side of formula")}if (any(whichNA <- is.na(match(vNames, names(x))))) {stop(sprintf(ngettext(sum(whichNA),"%s not available for plotting","%s not available for plotting"),onames[whichNA], collapse = ", "), domain = NA)}nV <- length(vNames) # number of variablesnG <- nrow(x) # number of groupsreVal <- vNam <- vVal <- vector("list", nV)vLevs <- vNam; names(vLevs) <- vNamesvType <- character(nV); names(vType) <- vNamesaux <- x[, reName]for(i in 1:nV) {obj <- x[, vNames[i]]if (inherits(obj, "factor") || is.character(obj)) {vType[i] <- "factor"obj <- as.factor(obj)vLevs[[i]] <- levels(obj)reVal[[i]] <- c(NA, NA, aux)vVal [[i]] <- c(0.5, length(levels(obj)) + 0.5, as.integer(obj))vNam [[i]] <- rep(vNames[i], nG + 2)} else { # numericvType[i] <- "numeric"reVal[[i]] <- auxvVal [[i]] <- objvNam [[i]] <- rep(vNames[i], nG)}}vNam <- unlist(vNam)argData <- data.frame(y = unlist(reVal), x = unlist(vVal),g = ordered(vNam, levels = vNames))## this is a hack to make this work, it's probably possible to## implement the whole thing much more succintly -- ds## The idea here is that the limits component of scales$x is going## to be a list -- and character vectors have special meaning as## limits, controlling both limits and the tick mark## positions/labelscondvar <- eval(expression(g), argData)xscales.lim <- as.list(levels(condvar))subsc <- seq_along(condvar)for (i in seq_along(xscales.lim)) {subscripts <- subsc[condvar == xscales.lim[[i]]]vN <- vNam[subscripts][1L]xscales.lim[[i]] <-if(vType[vN] == "numeric")range(argData$x[subscripts])else vLevs[vN][[1L]]}## --- further used from the panel() below: ---.drawLine <- pControl$drawLine.span <- pControl$span.loess.degree <- pControl$degree.loess## assign("panel.bwplot2", panel.bwplot2, where = 1)## assign(".cex", pControl$cex.axis)#, where = 1)## assign(".srt", pControl$srt.axis)#, where = 1)## assign(".mgp", pControl$mgp.axis)#, where = 1)xyplot(y ~ x | g, data = argData, subscripts = TRUE,scales = list(x = list(relation = "free", limits = xscales.lim)),panel = function(x, y, subscripts, ...) {vN <- vNam[subscripts][1L]if (grid) panel.grid()if (vType[vN] == "numeric") {panel.xyplot(x, y, ...)if (.drawLine) {panel.loess(x, y, span = .span, degree = .degree)}} else {panel.bwplot(x, y, horizontal = FALSE)if (.drawLine) {plot.line <- trellis.par.get("plot.line")panel.linejoin(x, y, fun = median, horizontal = FALSE,col.line = plot.line$col,lwd = plot.line$lwd,lty = plot.line$lty)}}},xlab = xlab %||% "", ylab = ylab %||% reName,strip = strip %||% strip.default, ...)}} ## {plot.ranef.lme}predict.lme <-function(object, newdata, level = Q, asList = FALSE,na.action = na.fail, ...){#### method for predict() designed for objects inheriting from class lme##Q <- object$dims$Qif (missing(newdata)) { # will return fitted valuesval <- fitted(object, level, asList)if (length(level) == 1) return(val)return(data.frame(object[["groups"]][,level[level != 0], drop = FALSE],predict = val))}maxQ <- max(level) # maximum level for predictionsnlev <- length(level)fixed <- formula(object)[-2L] # RHSTerms <- object$termsnewdata <- as.data.frame(newdata)if (maxQ > 0) { # predictions with random effectswhichQ <- Q - (maxQ-1):0reSt <- object$modelStruct$reStruct[whichQ]lmeSt <- lmeStruct(reStruct = reSt)groups <- getGroupsFormula(reSt)if (anyNA(match(all.vars(groups), names(newdata)))) {## groups cannot be evaluated in newdatastop("cannot evaluate groups for desired levels on 'newdata'")}} else {reSt <- NULL}## use xlev to make sure factor levels are the same as in contrasts## and to support character-type 'newdata' for factorscontr <- object$contrasts # these are in matrix formdataMix <- model.frame(formula = asOneFormula(formula(reSt), fixed),data = newdata, na.action = na.action,drop.unused.levels = TRUE,xlev = lapply(contr, rownames))origOrder <- row.names(dataMix) # preserve the original orderwhichRows <- match(origOrder, row.names(newdata))if (maxQ > 0) {## sort the model.frame by groups and get the matrices and parameters## used in the estimation proceduresgrps <- getGroups(newdata, # (unused levels are dropped here)eval(substitute(~ 1 | GRPS,list(GRPS = groups[[2]]))))## ordering data by groupsif (inherits(grps, "factor")) { # single levelgrps <- grps[whichRows]oGrps <- data.frame(grps)## checking if there are missing groupsif (any(naGrps <- is.na(grps))) {grps[naGrps] <- levels(grps)[1L] # input with existing level}ord <- order(grps) #"order" treats a single named argument peculiarlygrps <- data.frame(grps)row.names(grps) <- origOrdernames(grps) <- names(oGrps) <- as.character(deparse((groups[[2L]])))} else {grps <- oGrps <- grps[whichRows, ]## checking for missing groupsif (any(naGrps <- is.na(grps))) {## need to input missing groupsfor(i in names(grps)) {grps[naGrps[, i], i] <- levels(grps[,i])[1L]}naGrps <- t(apply(naGrps, 1, cumsum)) # propagating NAs}ord <- do.call(order, grps)## making group levels uniquefor(i in 2:ncol(grps)) {grps[, i] <-as.factor(paste(as.character(grps[, i-1]),as.character(grps[, i ]), sep = "/"))}}naGrps <- cbind(FALSE, naGrps)[ord, , drop = FALSE]grps <- grps[ord, , drop = FALSE]dataMix <- dataMix[ord, ,drop = FALSE]}## restore contrasts for the below model.matrix() calls (which may use## different factor variables, so we avoid passing the whole contr list)for(i in intersect(names(dataMix), names(contr))) {attr(dataMix[[i]], "contrasts") <- contr[[i]]}if (maxQ > 0) {revOrder <- match(origOrder, row.names(dataMix)) # putting in orig. orderZ <- model.matrix(reSt, dataMix)ncols <- attr(Z, "ncols")Names(lmeSt$reStruct) <- attr(Z, "nams")}N <- nrow(dataMix)X <- if (length(all.vars(fixed)) > 0) {model.matrix(fixed, model.frame(delete.response(Terms), dataMix))} else if(attr(terms(fixed), "intercept")) {array(1, c(N, 1), list(row.names(dataMix), "(Intercept)"))} else {array(, c(N, 0))}if (maxQ == 0) {## only population predictionsval <- if(ncol(X)) c(X %*% fixef(object)) else rep(0, nrow(X))attr(val, "label") <- "Predicted values"return(val)}ncols <- c(ncols, dim(X)[2L], 1)## creating the condensed linear modelattr(lmeSt, "conLin") <-list(Xy = array(c(Z, X, double(N)), c(N, sum(ncols)),list(row.names(dataMix), c(colnames(Z), colnames(X), "resp"))),dims = MEdims(grps, ncols))## Getting the appropriate BLUPs of the random effectsre <- object$coefficients$random[1:maxQ]for(i in names(re)) {ugrps <- unique(as.character(grps[, i]))val <- array(NA, c(length(ugrps), ncol(re[[i]])),list(ugrps, dimnames(re[[i]])[[2L]]))mGrps <- match(ugrps, dimnames(re[[i]])[[1L]])mGrps <- mGrps[!is.na(mGrps)]re[[i]] <- re[[i]][mGrps, , drop = FALSE]val[dimnames(re[[i]])[[1L]], ] <- re[[i]]re[[i]] <- val}attr(lmeSt, "lmeFit") <- list(beta = fixef(object), b = re)val <- fitted(lmeSt, level = 0:maxQ)val[as.logical(naGrps)] <- NA # setting missing groups to NA## putting back in original order and extracting levelsval <- val[revOrder, level + 1L] # predictionsif (maxQ > 1) { # making groups uniquefor(i in 2:maxQ)oGrps[, i] <-as.factor(paste(as.character(oGrps[,i-1]),as.character(oGrps[,i ]), sep = "/"))}if (nlev == 1) {grps <- as.character(oGrps[, level])if (asList) {val <- split(val, ordered(grps, levels = unique(grps)))} else {names(val) <- grps}lab <- "Predicted values"if (!is.null(aux <- attr(object, "units")$y)) {lab <- paste(lab, aux)}attr(val, "label") <- labval} else {data.frame(oGrps, predict = val)}}print.anova.lme <- function(x, verbose = attr(x, "verbose"), ...){ox <- xif ((rt <- attr(x,"rt")) == 1) { ## one objectif (!is.null(lab <- attr(x, "label"))) {cat(lab)if (!is.null(L <- attr(x, "L"))) {print(zapsmall(L), ...)}}pval <- format(round(x[, "p-value"],4))pval[as.double(pval) == 0] <- "<.0001"x[, "F-value"] <- format(zapsmall(x[, "F-value"]))x[, "p-value"] <- pvalprint(as.data.frame(x), ...)} else { ## several objectsif (verbose) {cat("Call:\n")objNams <- row.names(x)for(i in 1:rt) {cat(" ",objNams[i],":\n", sep ="")cat(" ",as.character(x[i,"call"]),"\n")}cat("\n")}x <- as.data.frame(x[,-1])for(i in names(x)) {xx <- x[[i]]if (i == "p-value") {xx <- round(xx, 4)xna <- is.na(xx)xx[!xna] <- format(xx[!xna])xx[as.double(xx) == 0] <- "<.0001"xx[xna] <- ""} else {if (match(i, c("AIC", "BIC", "logLik", "L.Ratio"), 0)) {xna <- is.na(xx)xx <- zapsmall(xx)xx[xna] <- 0xx <- format(xx)xx[xna] <- ""}}x[[i]] <- xx}print(as.data.frame(x), ...)}invisible(ox)}print.intervals.lme <- function(x, ...){cat(paste0("Approximate ", attr(x,"level") *100, "% confidence intervals\n"))for(i in names(x)) {aux <- x[[i]]cat("\n ",attr(aux, "label"), "\n", sep = "")attr(aux, "label") <- NULLif (i == "reStruct") {for(j in names(aux)) {cat(" Level:", j, "\n")print(as.matrix(aux[[j]]), ...)}} else if (i == "sigma")print(c(aux), ...)elseprint(as.matrix(aux), ...)}invisible(x)}print.lme <- function(x, ...){dd <- x$dimsif (inherits(x, "nlme")) { # nlme objectcat( "Nonlinear mixed-effects model fit by " )cat( if(x$method == "REML") "REML\n" else "maximum likelihood\n")cat(" Model:", deparse(x$call$model),"\n")} else { # lme objectscat( "Linear mixed-effects model fit by " )cat( if(x$method == "REML") "REML\n" else "maximum likelihood\n")}cat(" Data:", deparse( x$call$data ), "\n")if (!is.null(x$call$subset)) {cat(" Subset:", deparse(asOneSidedFormula(x$call$subset)[[2L]]),"\n")}cat(" Log-", if(x$method == "REML") "restricted-" else "","likelihood: ", format(x$logLik), "\n", sep = "")fixF <- x$call$fixedcat(" Fixed:",deparse(if(inherits(fixF, "formula") || is.call(fixF) || is.name(fixF))fixFelselapply(fixF, function(el) as.name(deparse(el)))), "\n")print(fixef(x), ...)cat("\n")print(summary(x$modelStruct), sigma = x$sigma, ...)cat("Number of Observations:", dd[["N"]])cat("\nNumber of Groups: ")Ngrps <- dd$ngrps[1:dd$Q]if ((lNgrps <- length(Ngrps)) == 1) { # single nestingcat(Ngrps,"\n")} else { # multiple nestingsNgrps <- 1:lNgrpsaux <- rep(names(Ngrps), sNgrps)aux <- split(aux, array(rep(sNgrps, lNgrps),c(lNgrps, lNgrps))[!lower.tri(diag(lNgrps))])names(Ngrps) <- unlist(lapply(aux, paste, collapse = " %in% "))cat("\n")print(rev(Ngrps), ...)}invisible(x)}print.ranef.lme <- function(x, ...){if (!inherits(x[[1L]], "data.frame")) {print.data.frame(x, ...)} else { # listfor(i in seq_along(x)) {cat("Level:", attr(x, "grpNames")[i],"\n")print.data.frame(x[[i]])if (i < length(x)) cat("\n")}}invisible(x)}print.summary.lme <- function(x, verbose = FALSE, ...){dd <- x$dimsverbose <- verbose || attr(x, "verbose")if (inherits(x, "nlme")) { # nlme objectcat( "Nonlinear mixed-effects model fit by " )cat( if(x$method == "REML") "REML\n" else "maximum likelihood\n")cat(" Model:", deparse(x$call$model),"\n")} else { # lme objectscat( "Linear mixed-effects model fit by " )cat( if(x$method == "REML") "REML\n" else "maximum likelihood\n")}## method <- x$methodcat(" Data:", deparse( x$call$data ), "\n")if (!is.null(x$call$subset)) {cat(" Subset:", deparse(asOneSidedFormula(x$call$subset)[[2L]]),"\n")}print(data.frame(AIC = x$AIC, BIC = x$BIC, logLik = c(x$logLik),row.names = " "), ...)if (verbose) cat("Convergence at iteration:",x$numIter,"\n")cat("\n")print(summary(x$modelStruct), sigma = x$sigma,reEstimates = x$coefficients$random, verbose = verbose, ...)fixF <- x$call$fixedcat("Fixed effects: ",deparse(if(inherits(fixF, "formula") || is.call(fixF))fixFelselapply(fixF, function(el) as.name(deparse(el)))),"\n")## fixed effects t-table and correlationsxtTab <- as.data.frame(x$tTable)wchPval <- match("p-value", names(xtTab))for(i in names(xtTab)[-wchPval]) {xtTab[, i] <- format(zapsmall(xtTab[, i]))}xtTab[,wchPval] <- format(round(xtTab[,wchPval], 4))if (any(wchLv <- (as.double(levels(xtTab[, wchPval])) == 0))) {levels(xtTab[, wchPval])[wchLv] <- "<.0001"}row.names(xtTab) <- dimnames(x$tTable)[[1L]]print(xtTab, ...)if (nrow(x$tTable) > 1) {corr <- x$corFixedclass(corr) <- "correlation"print(corr, title = " Correlation:", ...)}cat("\nStandardized Within-Group Residuals:\n")print(x$residuals, ...)cat("\nNumber of Observations:",x$dims[["N"]])cat("\nNumber of Groups: ")Ngrps <- dd$ngrps[1:dd$Q]if ((lNgrps <- length(Ngrps)) == 1) { # single nestingcat(Ngrps,"\n")} else { # multiple nestingsNgrps <- 1:lNgrpsaux <- rep(names(Ngrps), sNgrps)aux <- split(aux, array(rep(sNgrps, lNgrps),c(lNgrps, lNgrps))[!lower.tri(diag(lNgrps))])names(Ngrps) <- unlist(lapply(aux, paste, collapse = " %in% "))cat("\n")print(rev(Ngrps), ...)}invisible(x)}## coef(summary( obj )) # should work for "gls" or "lme" similarly as for lm():getCTable <- function (object, ...) object$tTableqqnorm.lme <-function(y, form = ~ resid(., type = "p"), abline = NULL,id = NULL, idLabels = NULL, grid = FALSE, ...)## normal probability plots for residuals and random effects{if (!inherits(form, "formula")) stop("'form' must be a formula")## object <- y## constructing dataallV <- all.vars(asOneFormula(form, id, idLabels))allV <- allV[is.na(match(allV,c("T","F","TRUE","FALSE")))]if (length(allV) > 0) {data <- getData(y)if (is.null(data)) { # try to construct dataalist <- lapply(as.list(allV), as.name)names(alist) <- allValist <- c(as.list(quote(data.frame)), alist)mode(alist) <- "call"data <- eval(alist, sys.parent(1))} else {if (any(naV <- is.na(match(allV, names(data))))) {stop(sprintf(ngettext(sum(naV),"%s not found in data","%s not found in data"),allV[naV]), domain = NA)}}} else data <- NULL## argument listargs <- list(...) # may be empty list()## appending object to datadata <- as.list(c(as.list(data), . = list(y)))## covariate - must always be presentcovF <- getCovariateFormula(form).x <- eval(covF[[2L]], data)labs <- attr(.x, "label")type <-if (inherits(.x, "ranef.lme"))"reff" # random effectselse if (!is.null(labs) && (labs == "Standardized residuals" ||labs == "Normalized residuals" ||substr(labs, 1, 9) == "Residuals"))"res" # residualselsestop("only residuals and random effects allowed")if (is.null(args$xlab)) args$xlab <- labsif (is.null(args$ylab)) args$ylab <- "Quantiles of standard normal"if(type == "res") { ## residuals ----------------------------------------fData <- qqnorm(.x, plot.it = FALSE)data[[".y"]] <- fData$xdata[[".x"]] <- fData$ydform <-if (!is.null(grp <- getGroupsFormula(form)))eval(substitute(.y ~ .x | G, list(G = grp[[2L]])))else.y ~ .xif (!is.null(id)) { # identify points in plotid <-switch(mode(id),numeric = {if (any(id <= 0) || any(id >= 1)) {stop("'Id' must be between 0 and 1")}if (labs == "Normalized residuals") {as.logical(abs(resid(y, type="normalized"))> -qnorm(id / 2))} else {as.logical(abs(resid(y, type="pearson"))> -qnorm(id / 2))}},call = eval(asOneSidedFormula(id)[[2L]], data),stop("'id' can only be a formula or numeric"))if (is.null(idLabels)) {idLabels <- getGroups(y)if (length(idLabels) == 0) idLabels <- seq_len(y$dims$N)idLabels <- as.character(idLabels)} else {if (mode(idLabels) == "call") {idLabels <-as.character(eval(asOneSidedFormula(idLabels)[[2L]], data))} else if (is.vector(idLabels)) {if (length(idLabels <- unlist(idLabels)) != length(id)) {stop("'idLabels' of incorrect length")}idLabels <- as.character(idLabels)} else {stop("'idLabels' can only be a formula or a vector")}}}} else { # type "ref" -- random.effects --------------------------------level <- attr(.x, "level")std <- attr(.x, "standardized")if (!is.null(effNams <- attr(.x, "effectNames"))) {.x <- .x[, effNams, drop = FALSE]}nc <- ncol(.x)nr <- nrow(.x)fData <- lapply(as.data.frame(.x), qqnorm, plot.it = FALSE)fData <- data.frame(.x = unlist(lapply(fData, function(x) x[["y"]])),.y = unlist(lapply(fData, function(x) x[["x"]])),.g = ordered(rep(names(fData),rep(nr, nc)),levels = names(fData)), check.names = FALSE)if (!is.null(grp <- getGroupsFormula(form))) {dform <- substitute(.y ~ .x | .g * GG, list(GG = deparse(grp[[2L]])))auxData <- data[is.na(match(names(data), "."))]} else {dform <- .y ~ .x | .gauxData <- list()}## id and idLabels - need not be presentif (!is.null(id)) { # identify points in plotN <- y$dims$Nid <-switch(mode(id),numeric = {if ((id <= 0) || (id >= 1)) {stop("'id' must be between 0 and 1")}aux <- ranef(y, level = level, standard = TRUE)as.logical(abs(c(unlist(aux))) > -qnorm(id / 2))},call = eval(asOneSidedFormula(id)[[2L]], data),stop("'id' can only be a formula or numeric"))if (length(id) == N) {## id as a formula evaluated in dataauxData[[".id"]] <- id}idLabels <-if (is.null(idLabels)) {rep(row.names(.x), nc)} else if (mode(idLabels) == "call") {as.character(eval(asOneSidedFormula(idLabels)[[2L]], data))} else if (is.vector(idLabels)) {if (length(idLabels <- unlist(idLabels)) != N)stop("'idLabels' of incorrect length")as.character(idLabels)} elsestop("'idLabels' can only be a formula or a vector")if (length(idLabels) == N) {## idLabels as a formula evaluated in dataauxData[[".Lid"]] <- idLabels}}data <-if (length(auxData)) { # need collapsingauxData <- gsummary(as.data.frame(auxData),groups = getGroups(y, level = level))auxData <- auxData[row.names(.x), , drop = FALSE]if (!is.null(auxData[[".id"]]))id <- rep(auxData[[".id"]], nc)if (!is.null(auxData[[".Lid"]]))idLabels <- rep(auxData[[".Lid"]], nc)cbind(fData, do.call(rbind, rep(list(auxData), nc)))} elsefData}id <- if (!is.null(id)) as.logical(as.character(id))idLabels <- as.character(idLabels)abl <- ablineif (is.null(args$strip))args$strip <- function(...) strip.default(..., style = 1)if (is.null(args$cex)) args$cex <- par("cex")if (is.null(args$adj)) args$adj <- par("adj")args <- c(list(dform, data = substitute(data)), args)if (is.null(args$panel))args$panel <- function(x, y, subscripts, ...) {x <- as.numeric(x)y <- as.numeric(y)dots <- list(...)if (grid) panel.grid()panel.xyplot(x, y, ...)if (any(ids <- id[subscripts])){ltext(x[ids], y[ids], idLabels[subscripts][ids],cex = dots$cex, adj = dots$adj)}if (!is.null(abl)) {if (length(abl) == 2)panel.abline(a = abl, ...)elsepanel.abline(h = abl, ...)}}if(type == "reff" && !std) {args[["scales"]] <- list(x = list(relation = "free"))}do.call(xyplot, as.list(args))}ranef.lme <-## Extracts the random effects from an lme object.## If aug.frame is true, the returned data frame is augmented with a## values from the original data object, if available. The variables## in the original data are collapsed over the cluster variable by the## function fun.function(object, augFrame = FALSE, level = 1:Q, data, which = 1:ncol(data),FUN = mean, standard = FALSE , omitGroupingFactor = TRUE,subset = NULL, ...){Q <- object$dims$Qeffects <- object$coefficients$randomif (Q > 1) {grpNames <- t(array(rep(rev(names(effects)), Q), c(Q, Q)))grpNames[lower.tri(grpNames)] <- ""grpNames <-rev(apply(grpNames, 1, function(x) paste(x[x != ""], collapse = " %in% ")))} else {grpNames <- names(effects)}effects <- effects[level]grpNames <- grpNames[level]if (standard) {for (i in names(effects)) {effects[[i]] <-t(t(effects[[i]]) /(object$sigma *sqrt(diag(as.matrix(object$modelStruct$reStruct[[i]])))))}}effects <- lapply(effects, as.data.frame)if (augFrame) {if (length(level) > 1) {stop("augmentation of random effects only available for single level")}effects <- effects[[1L]]effectNames <- names(effects)if (missing(data)) {data <- getData(object)}data <- as.data.frame(data)subset <- if (is.null(subset)) { # nlme caseeval(object$call[["naPattern"]])} else {asOneSidedFormula(as.list(match.call())[["subset"]])}if (!is.null(subset)) {subset <- eval(subset[[2L]], data)data <- data[subset, ,drop=FALSE]}data <- data[, which, drop = FALSE]## eliminating columns with same names as effectsdata <- data[, is.na(match(names(data), effectNames)), drop = FALSE]grps <- as.character(object[["groups"]][, level])data <- gsummary(data, FUN = FUN, groups = grps)if (omitGroupingFactor) {data <-data[, is.na(match(names(data), names(object$modelStruct$reStruct))),drop = FALSE]}if (length(data) > 0) {effects <- cbind(effects, data[row.names(effects),, drop = FALSE])}attr(effects, "effectNames") <- effectNames} else {effects <- lapply(effects,function(el) {attr(el, "effectNames") <- names(el)el})if (length(level) == 1) effects <- effects[[1L]]}structure(effects, class = c("ranef.lme", class(effects)),label= if (standard)"Standardized random effects"else"Random effects",level = max(level),standardized = standard,grpNames = grpNames)}residuals.lme <-function(object, level = Q, type = c("response", "pearson", "normalized"),asList = FALSE, ...){type <- match.arg(type)Q <- object$dims$Qval <- object[["residuals"]]if (is.character(level)) { # levels must be given consistentlynlevel <- match(level, names(val))if (any(aux <- is.na(nlevel))) {stop(sprintf(ngettext(sum(aux),"nonexistent level %s","nonexistent levels %s"),level[aux]), domain = NA)}level <- nlevel} else { # assuming integerslevel <- 1 + level}if (type != "response") { # standardize## have to standardize properly for when corStruct neq NULLval <- val[, level]/attr(val, "std")} else {val <- val[, level]}if (type == "normalized") {if (!is.null(cSt <- object$modelStruct$corStruct)) {## normalize according to inv-trans factorval <- recalc(cSt, list(Xy = as.matrix(val)))$Xy[, seq_along(level)]} else { # will just standardizedtype <- "pearson"}}if (length(level) == 1) {grps <- as.character(object[["groups"]][, max(c(1, level - 1))])if (asList) {val <- as.list(split(val, ordered(grps, levels = unique(grps))))} else {grp.nm <- row.names(object[["groups"]])val <- naresid(object$na.action, val)names(val) <- grps[match(names(val), grp.nm)]}attr(val, "label") <-switch(type,response = {if (!is.null(aux <- attr(object, "units")$y))paste("Residuals", aux)else "Residuals"},pearson = "Standardized residuals",normalized = "Normalized residuals")val} else naresid(object$na.action, val)}summary.lme <- function(object, adjustSigma = TRUE, verbose = FALSE, ...){## variance-covariance estimates for fixed effectsfixed <- fixef(object)stdFixed <- sqrt(diag(as.matrix(object$varFix)))object$corFixed <- array(t(object$varFix/stdFixed)/stdFixed,dim(object$varFix), list(names(fixed),names(fixed)))if (adjustSigma && object$method == "ML")stdFixed <- stdFixed *sqrt(object$dims$N/(object$dims$N - length(stdFixed)))## fixed effects coefficients, std. deviations and t-ratios##fDF <- object$fixDF[["X"]]tVal <- fixed/stdFixedobject$tTable <- cbind(Value = fixed, Std.Error = stdFixed, DF = fDF,"t-value" = tVal, "p-value" = 2 * pt(-abs(tVal), fDF))#### residuals##resd <- resid(object, type = "pearson")if (length(resd) > 5) {resd <- quantile(resd, na.rm = TRUE) # might have NAs from na.excludenames(resd) <- c("Min","Q1","Med","Q3","Max")}object$residuals <- resd#### generating the final object##aux <- logLik(object)object$BIC <- BIC(aux)object$AIC <- AIC(aux)structure(object, verbose = verbose, oClass = class(object),class = c("summary.lme", class(object)))}## based on R's update.defaultupdate.lme <-function (object, fixed., ..., evaluate = TRUE){call <- object$callif (is.null(call))stop("need an object with call component")extras <- match.call(expand.dots = FALSE)$...if (!missing(fixed.))call$fixed <- update.formula(formula(object), fixed.)if(length(extras) > 0) {existing <- !is.na(match(names(extras), names(call)))## do these individually to allow NULL to remove entries.for (a in names(extras)[existing]) call[[a]] <- extras[[a]]if(any(!existing))call <- as.call(c(as.list(call), extras[!existing]))}if(evaluate) eval(call, parent.frame())else call}## update.lme <-## function(object, fixed, data, random, correlation, weights, subset,## method, na.action, control, contrasts, ...)## {## thisCall <- as.list(match.call())[-(1:2)]## if (is.null(nextCall <- object$origCall) ||## !is.null(thisCall$fixed) ||## is.null(thisCall$random)) {## nextCall <- object$call## }## nextCall <- as.list(nextCall)[-1L]## if (is.null(thisCall$random) && is.null(thisCall$subset)) {## ## no changes in ranef model and no subsetting## thisCall$random <- object$modelStruct$reStruct## }## if (is.na(match("correlation", names(thisCall))) &&## !is.null(thCor <- object$modelStruct$corStruct)) {## thisCall$correlation <- thCor## }## if (is.na(match("weights", names(thisCall))) &&## !is.null(thWgt <- object$modelStruct$varStruct)) {## thisCall$weights <- thWgt## }## argNams <- unique( c(names(nextCall), names(thisCall)) )## args <- vector("list", length(argNams))## names(args) <- argNams## args[ names(nextCall) ] <- nextCall## nextCall <- args## if (!is.null(thisCall$fixed)) {## thisCall$fixed <- update(as.formula(nextCall$fixed), fixed)## }## nextCall[names(thisCall)] <- thisCall## do.call(lme, nextCall)## }Variogram.lme <-function(object, distance, form = ~1,resType = c("pearson", "response", "normalized"),data, na.action = na.fail, maxDist, length.out = 50,collapse = c("quantiles", "fixed", "none"), nint = 20, breaks,robust = FALSE, metric = c("euclidean", "maximum", "manhattan"),...){resType <- match.arg(resType)grps <- getGroups(object, level = object$dims$Q)## checking if object has a corSpatial elementcsT <- object$modelStruct$corStructwchRows <- NULLif (missing(distance)) {if (missing(form) && inherits(csT, "corSpatial")) {distance <- getCovariate(csT) # this excludes 1-obs groups} else {metric <- match.arg(metric)if (missing(data)) {data <- getData(object)}if (is.null(data)) { # will try to constructallV <- all.vars(form)if (length(allV) > 0) {alist <- lapply(as.list(allV), as.name)names(alist) <- allValist <- c(as.list(quote(data.frame)), alist)mode(alist) <- "call"data <- eval(alist, sys.parent(1))}}covForm <- getCovariateFormula(form)if (length(all.vars(covForm)) > 0) {if (attr(terms(covForm), "intercept") == 1) {covForm <- eval(substitute( ~ cFORM - 1, list(cFORM = covForm[[2L]])))}covar <- model.frame(covForm, data, na.action = na.action)## making sure grps is consistentwchRows <- !is.na(match(row.names(data), row.names(covar)))grps <- grps[wchRows, drop = TRUE]covar <- as.data.frame(unclass(model.matrix(covForm, covar)))} else {covar <-data.frame(dist = unlist(tapply(rep(1, nrow(data)), grps, cumsum)))}covar <- split(covar, grps)## getting rid of 1-observation groupscovar <- covar[sapply(covar, function(el) nrow(as.matrix(el))) > 1]distance <- lapply(covar,function(el, metric) dist(as.matrix(el), metric),metric = metric)}}res <- resid(object, type = resType)if (!is.null(wchRows)) {res <- res[wchRows]}res <- split(res, grps)res <- res[lengths(res) > 1L] # no 1-observation groups## levGrps <- levels(grps)val <- lapply(seq_along(res),function(i) Variogram(res[[i]], distance[[i]]))names(val) <- names(res)val <- do.call(rbind, val)if (!missing(maxDist)) {val <- val[val$dist <= maxDist, ]}collapse <- match.arg(collapse)if (collapse != "none") { # will collapse valuesdst <- val$distudist <- sort(unique(dst))ludist <- length(udist)if (!missing(breaks)) {if (min(breaks) > udist[1L]) breaks <- c(udist[1L], breaks)if (max(breaks) < udist[2L]) breaks <- c(breaks, udist[2L])if (!missing(nint) && nint != (length(breaks) - 1L)) {stop("'nint' is not consistent with 'breaks'")}nint <- length(breaks) - 1}cutDist <-if (nint < ludist) {if (missing(breaks))breaks <-if (collapse == "quantiles") { # break into equal groupsunique(quantile(dst, seq(0, 1, 1/nint), names=FALSE))} else { # fixed length intervalsseq(udist[1L], udist[length(udist)], length = nint + 1L)}cut(dst, breaks)}elsedstval <- lapply(split(val, cutDist),function(el) {vrg <- el$variogvrg <- if (robust)((mean(vrg^0.25))^4) / (0.457+ 0.494/nrow(el))elsemean(vrg)data.frame(variog = vrg,dist = median(el$dist))})val <- do.call(rbind, val)val$n.pairs <- as.vector(table(na.omit(cutDist)))val <- na.omit(val) # getting rid of NAs}row.names(val) <- 1:nrow(val)if (inherits(csT, "corSpatial") && resType != "normalized") {## will keep model variogramsig2 <- if (resType == "pearson") 1 else object$sigma^2attr(val, "modelVariog") <-Variogram(csT, sig2 = sig2, length.out = length.out)}structure(val, class = c("Variogram", "data.frame"),collapse = (collapse != "none"))}###*### lmeStruct - a model structure for lme fitslmeStruct <-## constructor for lmeStruct objectsfunction(reStruct, corStruct = NULL, varStruct = NULL){val <- list(reStruct = reStruct, corStruct = corStruct,varStruct = varStruct)structure(val[!vapply(val, is.null, NA)], # removing NULL componentssettings = attr(val$reStruct, "settings"),class = c("lmeStruct", "modelStruct"))}##*## lmeStruct methods for standard genericsfitted.lmeStruct <-function(object, level = Q, conLin = attr(object, "conLin"),lmeFit = attr(object, "lmeFit"), ...){if (is.null(conLin)) {stop("no condensed linear model")}if (is.null(lmeFit)) {stop("no fitted \"lme\" object")}dd <- conLin$dimsQ <- dd$QQp1 <- Q + 1Lnc <- dd$ncolfit <- array(0, c(dd$N, Qp1),list(dimnames(conLin$Xy)[[1L]], c("fixed", rev(names(object$reStruct)))))ZXstart <- rev(cumsum(c(1, nc[1:Q])))ZXend <- rev(cumsum(nc[1:Qp1]))ZXlen <- dd$ZXlen[Q:1]ZXngrps <- dd$ngrps[Q:1]ZXb <- lmeFit$bnc <- nc[Q:1]if(ZXstart[1L] <= ZXend[1L])fit[, "fixed"] <- # population fitted valuesconLin$Xy[, ZXstart[1L]:ZXend[1L], drop = FALSE] %*% lmeFit$betafor(i in 1:Q) {j <- i + 1Lfit[, j] <- fit[, i] +(conLin$Xy[, ZXstart[j]:ZXend[j], drop = FALSE] *ZXb[[i]][rep(1:ZXngrps[i], ZXlen[[i]]),,drop = FALSE]) %*% rep(1, nc[i])}## this is documented to return a vector for one level, matrix for more.## So it should be a matrix if there is only one row, but not if## there is only one columns.if(length(level) > 1) fit[, level + 1L, drop = FALSE] else fit[, level+1]}Initialize.lmeStruct <-function(object, data, groups, conLin = attr(object, "conLin"),control= list(niterEM = 20, gradHess = TRUE), ...){object[] <- lapply(object, Initialize, data, conLin, control)theta <- lapply(object, coef)len <- lengths(theta)pmap <- if (sum(len) > 0) {num <- seq_along(len)outer(rep(num, len), num, "==")} else {array(FALSE, c(1, length(len)))}dimnames(pmap) <- list(NULL, names(object))attr(object, "pmap") <- pmapif (length(object) == 1 && # only reStructall(attr(object, "settings")[-(1:3)] >= 0) && # known pdMat classcontrol[["gradHess"]]) {## can use numerical derivativesattr(object, "settings")[2:3] <- c(0, 1)class(object) <- c("lmeStructInt", class(object))}if (needUpdate(object)) {attr(object, "lmeFit") <- MEestimate(object, groups)update(object, data)} else {object}}logLik.lmeStruct <-function(object, Pars, conLin = attr(object, "conLin"), ...){coef(object) <- Pars # updating parameter valuesrecalc(object, conLin)[["logLik"]] # updating conLin}logLik.lmeStructInt <-function(object, Pars, conLin = attr(object, "conLin"), ...){## logLik for objects with reStruct parameters only, with## internally defined classq <- length(Pars)settings <- as.integer(attr(object, "settings"))aux <- .C(mixed_loglik, # >> ../src/nlmefit.cas.double(conLin[["Xy"]]), # ZXyas.integer(unlist(conLin$dims)), # pdims[]as.double(Pars), # pars[]settings, # settingsval = double(1 + q * (q + 1)), # logLik[] = (value, gradient, Hessian)double(1), # lRSSas.double(conLin$sigma) # sigma (17-11-2015; Fixed sigma patch ..))[["val"]]val <- aux[1L]attr(val, "gradient") <- -aux[1 + (1:q)]attr(val, "hessian") <- -array(aux[-(1:(q+1))], c(q, q))val}residuals.lmeStruct <-function(object, level = conLin$dims$Q, conLin = attr(object, "conLin"),lmeFit = attr(object, "lmeFit"), ...){conLin$Xy[, conLin$dims$ZXcols] - fitted(object, level, conLin, lmeFit)}varWeights.lmeStruct <- function(object){if (is.null(object$varStruct)) rep(1, attr(object, "conLin")$dims$N)else varWeights(object$varStruct)}## Auxiliary control functionslmeControl <-## Control parameters for lmefunction(maxIter = 50, msMaxIter = 50, tolerance = 1e-6, niterEM = 25,msMaxEval = 200,msTol = 1e-7, msVerbose = FALSE,returnObject = FALSE, gradHess = TRUE, apVar = TRUE,.relStep = .Machine$double.eps^(1/3), minAbsParApVar = 0.05,opt = c("nlminb", "optim"),optimMethod = "BFGS", natural = TRUE,sigma = NULL, ## 17-11-2015; Fixed sigma patch; SH Heisterkamp; Quantitative Solutionsallow.n.lt.q = FALSE, # 23-01-2019 (NA would be back compatible)...){if(is.null(sigma))sigma <- 0else if(!is.finite(sigma) || length(sigma) != 1 || sigma < 0)stop("Within-group std. dev. must be a positive numeric value")list(maxIter = maxIter, msMaxIter = msMaxIter, tolerance = tolerance,niterEM = niterEM, msMaxEval = msMaxEval, msTol = msTol,msVerbose = msVerbose, returnObject = returnObject,gradHess = gradHess , apVar = apVar, .relStep = .relStep,opt = match.arg(opt), optimMethod = optimMethod,minAbsParApVar = minAbsParApVar, natural = natural,sigma = sigma,allow.n.lt.q = allow.n.lt.q,...)}## Local Variables:## ess-indent-offset: 2## End: