[R-sig-ME] Patch for pedigreemm 0.3-3 plus questions

Roby Joehanes RobyJoehanes at hsl.harvard.edu
Wed Feb 8 20:20:38 CET 2017


Dear all:

It looks like lme4::lFormula or lme4::glFormula works. The time savings is about 40% now. Here is the code. If this code gets the blessings of the maintainers, I wonder if this code could be incorporated into the official pedigreemm.

Sincerely,
Roby

# Modified pedigreemm source
# Based on pedigreemm 0.3-3
# By Roby Joehanes

# What is modified:
# 1. Allowing optimizer options to pass through
# 2. Allow direct specification of pedigree matrix
# 3. Shortcut to reconstruct necessary matrices instead of calling lmer/glmer

pedigreemm <-
		function(formula, data, family = NULL, REML = TRUE, pedigree = list(),
				control = list(), start = NULL, verbose = FALSE, 
				subset, weights, na.action, offset, contrasts = NULL,
				model = TRUE, x = TRUE, ...)
{
	gaus <- FALSE
	if (is.null(family)) {
		gaus <- TRUE
	} else {
		## copied from glm()
		if (is.character(family)) 
			family <- get(family, mode = "function", envir = parent.frame())
		if (is.function(family)) 
			family <- family()
		if (!inherits(family, "family")) stop("unknown family type")
		gaus <- family$family == "gaussian" && family$link == "identity"
	}
	mc <- match.call()
	lmerc <- mc                         # create a call to lmer
	lmerc[[1]] <- if (gaus) as.name("lmer") else as.name("glmer")
	lmerc$pedigree <- NULL
	if (!gaus) lmerc$REML <- NULL
	
	if (!length(pedigree))              # call [g]lmer instead
		return(eval.parent(lmerc))
	
	stopifnot(is.list(pedigree),        # check the pedigree argument
			length(names(pedigree)) == length(pedigree),
			all(sapply(pedigree, function(x) is(x, "pedigree") | is(x, "matrix")))) # RJ modification
	
	lmerc[[1]] <- if (gaus) quote(lme4::lFormula) else quote(lme4::glFormula) # RJ modification
	lmf <- eval(lmerc, parent.frame())
	
	
	relfac <- pedigree          # copy the pedigree list for relfactor
	pnms <- names(pedigree)
	#pp <- lmf at pp # RJ modification
	#resp <- lmf at resp # RJ modification
	fl <- lmf$reTrms$flist # RJ modification
	stopifnot(all(pnms %in% names(fl)))
	asgn <- attr(fl, "assign")
	#Zt <- pp$Zt # RJ modification
	for (i in seq_along(pedigree)) {
		tn <- which(match(pnms[i], names(fl)) == asgn)
		if (length(tn) > 1)
			stop("a pedigree factor must be associated with only one r.e. term")
		ind <- (lmf$reTrms$Gp)[tn:(tn+1L)] # RJ modification
		rowsi <- (ind[1]+1L):ind[2]
		if (is(relfac[[i]], "pedigree")) relfac[[i]] <- relfactor(pedigree[[i]], rownames(lmf$reTrms$Zt)[rowsi]) # RJ modification
		lmf$reTrms$Zt[rowsi,] <- relfac[[i]] %*% lmf$reTrms$Zt[rowsi,] # RJ modification
	}
	#reTrms <- list(Zt=Zt,theta=lmf at theta,Lambdat=pp$Lambdat,Lind=pp$Lind,  # RJ modification starts
	#		lower=lmf at lower,flist=lmf at flist,cnms=lmf at cnms, Gp=lmf at Gp)
	dfl <- list(fr=lmf$fr, X=lmf$X, reTrms=lmf$reTrms, start=lmf$reTrms$theta)
	optimizer_opt <- ifelse(gaus, control$optimizer, control$optimizer[[2]]);
	if (is.null(optimizer_opt)) optimizer_opt <- "Nelder_Mead"; # RJ modification ends
	if (gaus) {
		dfl$REML = lmf$REML > 0L # RJ modification
		devfun <- do.call(mkLmerDevfun,dfl)
		opt <- optimizeLmer(devfun, optimizer=optimizer_opt,  # RJ modification starts
			restart_edge = control$restart_edge,
			boundary.tol = control$boundary.tol,
			control = control$optCtrl,
			calc.derivs=control$calc.derivs,
			use.last.params=control$use.last.params,...) # RJ modification ends
	} else {
		dfl$family <- family
		devfun <- do.call(mkGlmerDevfun,dfl)
		opt <- optimizeGlmer(devfun, optimizer=optimizer_opt, # RJ modification starts
			restart_edge=control$restart_edge,
			boundary.tol=control$boundary.tol,
			control = control$optCtrl,
			stage=2,
			calc.derivs=control$calc.derivs,
			use.last.params=control$use.last.params,...) # RJ modification ends
	}
	mm <- mkMerMod(environment(devfun), opt, lmf$reTrms, lmf$fr, mc)  # RJ modification
	cls <- if (gaus) "lmerpedigreemm" else "glmerpedigreemm"
	ans <- do.call(new, list(Class=cls, relfac=relfac,
					frame=mm at frame, flist=mm at flist, cnms=mm at cnms, Gp=mm at Gp,
					theta=mm at theta, beta=mm at beta,u=mm at u,lower=mm at lower,
					devcomp=mm at devcomp, pp=mm at pp,resp=mm at resp,optinfo=mm at optinfo))
	ans at call <- evalq(mc)
	ans
}



-----Original Message-----
From: R-sig-mixed-models [mailto:r-sig-mixed-models-bounces at r-project.org] On Behalf Of Roby Joehanes
Sent: Wednesday, February 8, 2017 1:52 PM
To: r-sig-mixed-models at r-project.org
Subject: [R-sig-ME] Patch for pedigreemm 0.3-3 plus questions

Dear all:

Attached please find the patch for pedigreemm 0.3-3, with the following changes:
1. Control options are now passed through to the optimizeLmer / optimizeGlmer, including optimizer, calc.derivs, etc. This saves about 15% of time.
2. Allowing direct matrix specification on pedigree. This will allow broader application in genetics, such as allowing cryptic relatedness to stand in as pedigree matrix.

A few questions from me. I think pedigreemm tries to call lmer / glmer once to get @pp (for Zt, primarily, but also X, Lambdat, and Lind), @resp (only for REML), @flist and @Gp, then followed up with optimizeLmer or optimizeGlmer. I think it is a big waste of time since most of these can be constructed offline (i.e., without actually computing the results), like in pedigreemm version 1.1 or so. Is there a way in lme4 package to do that instead of calling lmer / glmer? Is lme4::lFormula / lme4::glFormula the right way? Did I overlook something?

Thank you!

Sincerely,
Roby



----------------------------------------------------------------------
CONFIDENTIAL NOTICE:

This electronic mail transmission contains confidential information including Protected Health Information (PHI) that is legally privileged. 
If you are not the intended recipient, or designee, you are hereby notified that any disclosure, copying, distribution or use of any and all attachments to this transmission is STRICTLY PROHIBITED. If you have received this transmission in error, please notify the sender immediately to arrange for return or destruction of these documents.
_______________________________________________
R-sig-mixed-models at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-sig-mixed-models

----------------------------------------------------------------------
CONFIDENTIAL NOTICE:

This electronic mail transmission contains confidential information 
including Protected Health Information (PHI) that is legally privileged. 
If you are not the intended recipient, or designee, you are hereby 
notified that any disclosure, copying, distribution or use of any and
all attachments to this transmission is STRICTLY PROHIBITED. If you 
have received this transmission in error, please notify the sender 
immediately to arrange for return or destruction of these documents.



More information about the R-sig-mixed-models mailing list