Nothing
# Automatically generated from the noweb directory
lmekin <- function(formula, data,
weights, subset, na.action,
control, varlist, vfixed, vinit,
method=c("ML", "REML"),
x=FALSE, y=FALSE, model=FALSE,
random, fixed, variance, ...) {
Call <- match.call()
sparse <- c(1,0) #needed for compatablily with coxme code
if (!missing(fixed)) {
if (missing(formula)) {
formula <- fixed
warning("The 'fixed' argument of lmekin is depreciated")
}
else stop("Both a fixed and a formula argument are present")
}
if (!missing(random)) {
warning("The random argument of lmekin is depreciated")
if (!inherits(random, 'formula') || length(random) !=2)
stop("Invalid random formula")
j <- length(formula) #will be 2 or 3, depending on if there is a y
# Add parens to the random formula and paste it on
formula[[j]] <- call('+', formula[[j]], call('(', random[[2]]))
}
if (!missing(variance)) {
warning("The variance argument of lmekin is depreciated")
vfixed <- variance
}
method <- match.arg(method)
temp <- call('model.frame', formula= subbar(formula))
for (i in c('data', 'subset', 'weights', 'na.action'))
if (!is.null(Call[[i]])) temp[[i]] <- Call[[i]]
m <- eval.parent(temp)
Y <- model.extract(m, "response")
n <- length(Y)
if (n==0) stop("data has no observations")
weights <- model.weights(m)
if (length(weights) ==0) weights <- rep(1.0, n)
else if (any(weights <=0))
stop("Negative or zero weights are not allowed")
offset <- model.offset(m)
if (length(offset)==0) offset <- rep(0., n)
# Check for penalized terms; the most likely is pspline
pterms <- sapply(m, inherits, 'coxph.penalty')
if (any(pterms)) {
stop("You cannot have penalized terms in lmekin")
}
if (missing(control)) control <- lmekin.control(...)
flist <- formula1(formula)
if (hasAbar(flist$fixed))
stop("Invalid formula: a '|' outside of a valid random effects term")
special <- c("strata", "cluster")
Terms <- terms(flist$fixed, special)
if (length(attr(Terms, "specials")$strata))
stop ("A strata term is invalid in lmekin")
if (length(attr(Terms, "specials")$cluster))
stop ("A cluster term is invalid in lmekin")
X <- model.matrix(Terms, m)
nrandom <- length(flist$random)
if (nrandom ==0) stop("No random effects terms found")
vparm <- vector('list', nrandom)
is.variance <- rep(TRUE, nrandom) #penalty fcn returns a variance or penalty?
ismat <- function (x) {
inherits(x, c("matrix", "bdsmatrix", "Matrix"), which=FALSE)
}
if (missing(varlist) || is.null(varlist)) {
varlist <- vector('list', nrandom)
for (i in 1:nrandom) varlist[[i]] <- coxmeFull() #default
}
else {
if (is.function(varlist)) varlist <- varlist()
if (inherits(varlist, 'coxmevar')) varlist <- list(varlist)
else if (ismat(varlist))
varlist <- list(coxmeMlist(list(varlist)))
else {
if (!is.list(varlist)) stop("Invalid varlist argument")
if (all(sapply(varlist, ismat))) {
# A list of matrices
if (nrandom >1)
stop(paste("An unlabeled list of matrices is",
"ambiguous when there are multiple random terms"))
else varlist <- list(coxmeMlist(varlist))
}
else { #the user gave me a list, not all matrices
for (i in 1:length(varlist)) {
if (is.function(varlist[[i]]))
varlist[[i]] <-varlist[[i]]()
if (ismat(varlist[[i]]))
varlist[[i]] <- coxmeMlist(list(varlist[[i]]))
if (!inherits(varlist[[i]], 'coxmevar')) {
if (is.list(varlist[[i]])) {
if (all(sapply(varlist[[i]], ismat)))
varlist[[i]] <- coxmeMlist(varlist[[i]])
else stop("Invalid varlist element")
}
else stop("Invalid varlist element")
}
}
}
}
while(length(varlist) < nrandom) varlist <- c(varlist, list(coxmeFull()))
}
if (!is.null(names(varlist))) { # put it in the right order
vname <- names(varlist)
stop("Cannot (yet) have a names varlist")
indx <- pmatch(vname, names(random), nomatch=0)
if (any(indx==0 & vname!=''))
stop(paste("Varlist element not matched:", vname[indx==0 & vname!='']))
if (any(indx>0)) {
temp <- vector('list', nrandom)
temp[indx] <- varlist[indx>0]
temp[-indx]<- varlist[indx==0]
varlist <- temp
}
}
#check validity (result is never used)
check <- sapply(varlist, function(x) {
fname <- c("initialize", "generate", "wrapup")
indx <- match(fname, names(x))
if (any(is.na(x)))
stop(paste("Member not found in variance function:",
fname(is.na(indx))))
if (length(x) !=3 || any(!sapply(x, is.function)))
stop("Varlist objects must consist of exaclty three functions")
})
getcmat <- function(x, mf) {
if (is.null(x) || x==1) return(NULL)
Terms <- terms(eval(call("~", x)))
attr(Terms, 'intercept') <- 0 #ignore any "1+" that is present
varnames <- attr(Terms, 'term.labels')
ftemp <- sapply(mf[varnames], is.factor)
if (any(ftemp)) {
clist <- lapply(mf[varnames[ftemp]],
function(x) diag(length(levels(x))))
model.matrix(Terms, mf, contrasts.arg =clist)
}
else model.matrix(Terms, mf)
}
getGroupNames <- function(x) {
if (is.call(x) && x[[1]]==as.name('/'))
c(getGroupNames(x[[2]]), getGroupNames(x[[3]]))
else deparse(x)
}
getgroups <- function(x, mf) {
if (is.numeric(x)) return(NULL) # a shrinkage effect like (x1+x2 | 1)
varname <- getGroupNames(x)
indx <- match(varname, names(mf), nomatch=0)
if (any(indx==0)) stop(paste("Invalid grouping factor", varname[indx==0]))
else data.frame(lapply(mf[indx], as.factor))
}
if (missing(vinit) || is.null(vinit)) vinit <- vector('list', nrandom)
else {
if (nrandom==1) {
if (is.numeric(vinit)) vinit <- list(vinit)
else if (is.list(vinit)) vinit <- list(unlist(vinit))
}
if (!is.list(vinit)) stop("Invalid value for `vinit` parameter")
if (length(vinit) > nrandom)
stop (paste("Vinit must be a list of length", nrandom))
if (!all(sapply(vinit, function(x) (is.null(x) || is.numeric(x)))))
stop("Vinit must contain numeric values")
if (length(vinit) < nrandom)
vinit <- c(vinit, vector('list', nrandom - length(vinit)))
tname <- names(vinit)
if (!is.null(tname)) {
stop("Named initial values not yet supported")
#temp <- pmatch(tname, names(flist$random), nomatch=0)
#temp <- c(temp, (1:nrandom)[-temp])
#vinit <- vinit[temp]
}
}
if (missing(vfixed) || is.null(vfixed)) vfixed <- vector('list', nrandom)
else {
if (nrandom==1) {
if (is.numeric(vfixed)) vfixed <- list(vfixed)
else if (is.list(vfixed)) vfixed <- list(unlist(vfixed))
}
if (!is.list(vfixed)) stop("Invalid value for `vfixed` parameter")
if (length(vfixed) > nrandom)
stop (paste("Vfixed must be a list of length", nrandom))
if (!all(sapply(vfixed, function(x) (is.null(x) || is.numeric(x)))))
stop("Vfixed must contain numeric values")
if (length(vfixed) < nrandom)
vfixed <- c(vfixed, vector('list', nrandom - length(vfixed)))
tname <- names(vfixed)
if (!is.null(tname)) {
temp <- pmatch(tname, names(flist$random), nomatch=0)
temp <- c(temp, (1:nrandom)[-temp])
vfixed <- vfixed[temp]
}
}
newzmat <- function(xmat, xmap) {
n <- nrow(xmap)
newz <- matrix(0., nrow=n, ncol=max(xmap))
for (i in 1:ncol(xmap))
newz[cbind(1:n, xmap[,i])] <- xmat[,i]
newz
}
fmat <- zmat <- matrix(0, nrow=n, ncol=0)
ntheta <- integer(nrandom)
ncoef <- matrix(0L, nrandom, 2, dimnames=list(NULL, c("intercept", "slope")))
itheta <- NULL #initial values of parameters to iterate over
for (i in 1:nrandom) {
f2 <- formula2(flist$random[[i]])
if (f2$intercept & f2$group==1)
stop(paste("Error in random term ", i,
": Random intercepts require a grouping variable", sep=''))
vfun <- varlist[[i]]
if (!is.null(f2$interaction)) stop("Interactions not yet written")
cmat <- getcmat(f2$fixed, m)
groups <- getgroups(f2$group, m)
ifun <- vfun$initialize(vinit[[i]], vfixed[[i]], intercept=f2$intercept,
groups, cmat, control)
if (!is.null(ifun$error))
stop(paste("In random term ", i, ": ", ifun$error, sep=''))
vparm[[i]] <- ifun$parms
if (!is.null(ifun$is.variance)) is.variance[i] <- ifun$is.variance
itheta <- c(itheta, ifun$theta)
ntheta[i] <- length(ifun$theta)
if (f2$intercept) {
if (!is.matrix(ifun$imap) || nrow(ifun$imap) !=n)
stop(paste("In random term ", i,
": Invalid intercept matrix F", sep=''))
temp <- sort(unique(c(ifun$imap)))
if (any(temp != 1:length(temp)))
stop(paste("In random term ", i,
": intercept matrix has an invalid element", sep=''))
if (ncol(fmat) >0) fmat <- cbind(fmat, ifun$imap + max(fmat))
else fmat <- ifun$imap
ncoef[i,1] <- 1+ max(ifun$imap) - min(ifun$imap)
}
if (length(cmat)>0) {
if (is.null(ifun$xmap) || is.null(ifun$X) ||
!is.matrix(ifun$xmap) || !is.matrix(ifun$X) ||
nrow(ifun$xmap) !=n || nrow(ifun$X) != n ||
ncol(ifun$xmap) != ncol(ifun$X))
stop(paste("In random term ", i,
"invalid X/xmap pair"))
if (f2$intercept) xmap <- ifun$xmap - max(ifun$imap)
else xmap <- ifun$xmap
if (any(sort(unique(c(xmap))) != 1:max(xmap)))
stop(paste("In random term ", i,
": xmap matrix has an invalid element", sep=''))
temp <- newzmat(ifun$X, xmap)
ncoef[i,2] <- ncol(temp)
zmat <- cbind(zmat, temp)
}
}
if (any(is.variance) & !all(is.variance))
stop("All variance terms must have the same is.variance setting")
kfun <- function(theta, varlist, vparm, ntheta, ncoef) {
nrandom <- length(varlist)
sindex <- rep(1:nrandom, ntheta) #which thetas to which terms
tmat <- varlist[[1]]$generate(theta[sindex==1], vparm[[1]])
dd <- dim(tmat)
if (length(dd) !=2 || any(dd != rep(ncoef[1,1]+ncoef[1,2], 2)))
stop("Incorrect dimensions for generated penalty matrix, term 1")
if (!inherits(tmat, 'bdsmatrix'))
tmat <- bdsmatrix(blocksize=integer(0), blocks=numeric(0), rmat=tmat)
if (nrandom ==1) return(tmat)
# Need to build up the matrix by pasting up a composite R
nsparse <- sum(tmat@blocksize)
nrow.R <- sum(ncoef)
ncol.R <- nrow.R - nsparse
R <- matrix(0., nrow.R, ncol.R)
indx1 <- 0 #current column offset wrt intercepts
indx2 <- sum(ncoef[,1]) -nsparse #current col offset wrt filling in slopes
if (ncol(tmat) > nsparse) { #first matrix has an rmat component
if (ncoef[1,1] > nsparse) { #intercept contribution to rmat
irow <- 1:ncoef[1,1] #rows for intercepts
j <- ncoef[1,1] - nsparse #number of dense intercept columns
R[irow, 1:j] <- tmat@rmat[irow,1:j]
indx1 <- j #number of intercept processed so far
if (ncoef[1,2] >0) {
# T[1-62, 3-66] of the example above
k <- 1:ncoef[1,2]
R[irow, k+indx2-nsparse] <- tmat@rmat[irow, k+j]
}
}
else j <- 0
if (ncoef[1,2] >0) { #has a slope contribution to rmat
# T[63-128, 3-66] of the example above
k <- 1:ncoef[1,2]
R[k+indx2 +nsparse, k+ indx2] <- tmat@rmat[k+indx1, j+k]
indx2 <- indx2 + ncoef[1,2] #non intercetps so far
}
}
for (i in 2:nrandom) {
temp <- as.matrix(varlist[[i]]$generate(theta[sindex==i], vparm[[i]]))
if (any(dim(temp) != rep(ncoef[i,1]+ncoef[i,2], 2)))
stop(paste("Invalid dimension for generated penalty matrix, term",
i))
if (ncoef[i,1] >0) { # intercept contribution
#U or V [1-8, 1-8] in the example above
j <- ncoef[i,1]
R[indx1 +1:j + nsparse, indx1 +1:j] <- temp[1:j,1:j]
if (ncoef[i,2] >0) {
# V[1-8, 9-24] in the example
k <- 1:ncoef[i,2]
R[indx1+ 1:j + nsparse, indx2 +k] <- temp[1:j, k+ j]
# V[9-24, 9-24]
R[indx2+k +nsparse, indx2 +k] <- temp[k+j, k+j]
}
}
else if (ncoef[i,2]>0) {
k <- 1:ncoef[i,2]
R[indx2+k +nsparse, indx2+k] <- temp
}
indx1 <- indx1 + ncoef[i,1]
indx2 <- indx2 + ncoef[i,2]
}
bdsmatrix(blocksize=tmat@blocksize, blocks=tmat@blocks, rmat=R)
}
#Define Z^* and X^*
itemp <- split(row(fmat), fmat)
zstar1 <- new("dgCMatrix",
i= as.integer(unlist(itemp) -1),
p= as.integer(c(0, cumsum(unlist(lapply(itemp, length))))),
Dim=as.integer(c(n, max(fmat))),
Dimnames= list(NULL, NULL),
x= rep(1.0, length(fmat)),
factors=list())
if (length(zmat) >0) {
# there were random slopes as well
zstar1 <- cbind(zstar1, as(Matrix(zmat), "dgCMatrix"))
}
nfrail <- ncol(zstar1)
nvar <- ncol(X)
if (nvar == 0) xstar <- NULL #model with no covariates
else xstar <- rbind(Matrix(X, sparse=FALSE),
matrix(0., nrow=nfrail, ncol=ncol(X)))
ystar <- c(Y, rep(0.0, nfrail))
mydiag <- function(x) {
if (inherits(x, "sparseQR")) diag(x@R)
else diag(qr.R(x))
}
logfun <- function(theta, best=0) {
vmat <- kfun(theta, varlist, vparm, ntheta, ncoef)
Delta <- t(solve(chol(as(vmat, "dsCMatrix"), pivot=FALSE)))
zstar <- rbind(zstar1, Delta)
qr1 <- qr(zstar)
dd <- mydiag(qr1)
cvec <- as.vector(qr.qty(qr1, ystar))[-(1:nfrail)] #residual part
if (nvar >0) { # have covariates
qr2 <- qr(qr.qty(qr1, xstar)[-(1:nfrail),])
cvec <- qr.qty(qr2, cvec)[-(1:nvar)] #residual part
if (method!= "ML") dd <- c(dd, mydiag(qr2))
}
loglik <- sum(log(abs(diag(Delta)))) - sum(log(abs(dd)))
if (method=="ML") loglik <- loglik - .5*n*log(sum(cvec^2))
else loglik <- loglik - .5*length(cvec)*log(sum(cvec^2))
best - (loglik+1) #optim() wants to minimize rather than maximize
}
nstart <- sapply(itheta, length)
if (length(nstart) ==0) theta <- NULL #no thetas to solve for
else {
#iteration is required
#make a matrix of all possible starting estimtes
testvals <- do.call(expand.grid, itheta)
bestlog <- NULL
for (i in 1:nrow(testvals)) {
ll <- logfun(as.numeric(testvals[i,]))
if (is.finite(ll)) {
#ll calc can fail if someone picks a very bad starting guess
if (is.null(bestlog) || ll < bestlog) {
# (optim is set up to minimize)
bestlog <- ll
theta <- as.numeric(testvals[i,])
}
}
}
if (is.null(bestlog))
stop("No starting estimate was successful")
optpar <- control$optpar
optpar$hessian <- TRUE
mfit <- do.call('optim', c(list(par= theta, fn=logfun, gr=NULL,
best=bestlog), optpar))
theta <- mfit$par
}
vmat <- kfun(theta, varlist, vparm, ntheta, ncoef)
Delta <- t(solve(chol(as(vmat, "dsCMatrix"), pivot=FALSE)))
zstar <- rbind(zstar1, Delta)
qr1 <- qr(zstar)
dd <- mydiag(qr1)
ctemp <- as.vector(qr.qty(qr1, ystar))
cvec <- ctemp[-(1:nfrail)] #residual part
if (is.null(xstar)) { #No X covariates
rcoef <- qr.coef(qr1, ystar)
yhat <- qr.fitted(qr1, ystar)
}
else {
qtx <- qr.qty(qr1, xstar)
qr2 <- qr(qtx[-(1:nfrail),,drop=F])
if (method!="ML") dd <- c(dd, mydiag(qr2))
fcoef <-qr.coef(qr2, cvec)
yresid <- ystar - xstar %*% fcoef
rcoef <- qr.coef(qr1, yresid)
cvec <- qr.qty(qr2, cvec)[-(1:nvar)] #residual part
if (inherits(qr2, "sparseQR")) varmat <- chol2inv(qr2@R)
else varmat <- chol2inv(qr.R(qr2))
yhat <- as.vector(zstar1 %*% rcoef + X %*% fcoef) #kill any names
}
if (method=="ML") {
sigma2 <- sum(cvec^2)/n #MLE estimate
loglik <- sum(log(abs(diag(Delta)))) -
(sum(log(abs(dd))) + .5*n*(log(2*pi) +1 + log(sigma2)))
}
else {
np <- length(cvec) # n-p
sigma2 <- mean(cvec^2) # divide by n-p
loglik <- sum(log(abs(diag(Delta)))) -
(sum(log(abs(dd))) + .5*np*(log(2*pi) + 1+ log(sigma2)))
}
# Debugging code, set the argument to TRUE only during testing
if (FALSE) {
# Compute the alternate way (assumes limited reordering)
zx <- cbind(zstar, as(xstar, class(zstar)))
qr3 <- qr(zx)
cvec3 <- qr.qty(qr3, ystar)[-(1:(nvar+nfrail))]
if (method=="ML") dd3 <- (diag(myqrr(qr3)))[1:nfrail]
else dd3 <- (diag(myqrr(qr3)))[1:(nfrail+nvar)]
#all.equal(dd, dd3)
#all.equal(cvec, cvec3)
acoef <- qr.coef(qr3, ystar)
browser()
}
newtheta <- random.coef <- list()
nrandom <- length(varlist)
sindex <- rep(1:nrandom, ntheta) #which thetas to which terms
bindex <- rep(1:nrandom, rowSums(ncoef)) # which b's to which terms
for (i in 1:nrandom) {
temp <- varlist[[i]]$wrapup(theta[sindex==i], rcoef[bindex==i],
vparm[[i]])
newtheta <- c(newtheta, lapply(temp$theta, function(x) x*sigma2))
if (!is.list(temp$b)) {
temp$b <- list(temp$b)
names(temp$b) <- paste("Random", i, sep='')
}
random.coef <- c(random.coef, temp$b)
}
if (length(fcoef) >0) {
# There are fixed effects
nvar <- length(fcoef)
fit <- list (coefficients=list(fixed=fcoef, random=random.coef),
var = varmat * sigma2,
vcoef =newtheta,
residuals= Y- yhat,
method=method,
loglik=loglik,
sigma=sqrt(sigma2),
n=n,
call=Call)
}
else fit <- list(coefficients=list(fixed=NULL, random=random.coef),
vcoef=newtheta,
residuals=Y - yhat,
method=method,
loglik=loglik,
sigma=sqrt(sigma2),
n=n,
call=Call)
if (!is.null(theta)) {
fit$rvar <- mfit$hessian
fit$iter <- mfit$counts
}
if (x) fit$x <- X
if (y) fit$y <- Y
if (model) fit$model <- m
na.action <- attr(m, "na.action")
if (length(na.action)) fit$na.action <- na.action
class(fit) <- "lmekin"
fit
}
residuals.lmekin <- function(object, ...) {
if (length(object$na.action)) naresid(object$.na.action, object$residuals)
else object$residuals
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.