[R-sig-ME] perturb with lme4
Austin Frank
austin.frank at gmail.com
Fri Aug 17 23:26:06 CEST 2007
Hello!
I'd like to evaluate the degree of colinearity introduced into my model
by two categorical independent variables. I'd like to use a
perturbation analysis, and so reached for the 'perturb' package.
Unfortunately, the perturb function as written doesn't work with lmer
models.
The funtion directly accesses the "call" slot of its model argument (frm
<- mod$call$formula, for example). I attempted the obvious fix of
either using an accessor function (frm <- formula(mod)) or using the
right slotting operator (frm <- mod at call$frm). This naive replacement
attempt didn't get me very far.
Can anyone suggest a way to modify the perturb function as written, some
work-alike code for an lmer model, or an alternative way for assessing
colinearity introduced by categorical variables in an lmer model?
My (half-hearted) attempt at a modified perturb function is below.
Thanks,
/au
## should be called with
# ptb <- my.perturb(mod.lmer,
# pfac=list(
# list("fac1",pcnt=95),
# list("fac2",pcnt=95)))
my.perturb <- function
( mod, pvars = NULL,
prange = NULL,
ptrans = NULL,
pfac = NULL,
uniform = FALSE,
niter = 100)
{
cutsp <- function(indx, tbl) {
findInterval(runif(1), tbl[indx, ], rightmost.closed = TRUE)
}
if (is.null(formula(mod)))
stop("First argument does not contain a formula")
stopifnot(is.list(pfac) || is.null(pfac))
nms <- all.vars(terms(mod))
stopifnot(all(pvars %in% nms))
result <- NULL
ncases <- length(get(nms[1]))
frm <- deparse(formula(mod), width.cutoff = 500)
result$formula <- frm
allb <- coefficients(mod)
if (length(pvars) > 0) {
stopifnot(is.vector(get(pvars)))
stopifnot(length(pvars) == length(prange))
result$pvars <- pvars
result$prange <- prange
if (length(ptrans) > 0)
result$ptrans <- ptrans
b <- make.names(c(nms, pvars), unique = TRUE)
pvars.1 <- b[(length(nms) + 1):length(b)]
for (i in 1:length(pvars)) {
inp <- paste("\\<", pvars[i], "(\\>[^.]|$)", sep = "")
outp <- paste(pvars.1[i], "\\1", sep = "")
frm <- gsub(inp, outp, frm)
ptrans <- gsub(inp, outp, ptrans)
}
result$ptrans2 <- ptrans
}
if (length(pfac[[1]]) > 0) {
rcls.tbl <- NULL
pfac.1 <- NULL
if (is.list(pfac[[1]]))
n <- length(pfac)
else n <- 1
for (i in 1:n) {
if (n == 1)
lstnm <- pfac
else lstnm <- pfac[[i]]
stopifnot(all(lstnm[[1]] %in% nms))
b <- make.names(c(nms, lstnm[[1]]), unique = TRUE)
pfc <- b[(length(nms) + 1):length(b)]
inp <- paste("\\<", lstnm[[1]], "(\\>[^.]|$)", sep = "")
outp <- paste(pfc, "\\1", sep = "")
frm <- gsub(inp, outp, frm)
rcls <- do.call("reclassify", lstnm)
rcls.tbl <- c(rcls.tbl, list(rcls))
pfac.1 <- c(pfac.1, pfc)
}
result$reclassify.tables <- rcls.tbl
}
result$formula2 <- frm
mod at call$formula <- as.formula(frm)
if (uniform) {
ranexp <- "runif(ncases,-prange[i],prange[i])"
result$distribution <- "uniform"
}
else {
ranexp <- "rnorm(ncases,0,prange[i])"
result$distribution <- "normal"
}
for (k in 1:niter) {
if (length(prange) > 0) {
for (i in 1:length(prange)) {
assign(pvars.1[i], get(pvars[i]) + eval(parse(text = ranexp))
}
}
for (trans in ptrans) eval(trans)
if (length(pfac[[1]]) > 0) {
for (i in 1:length(rcls.tbl)) {
tbl <- rcls.tbl[[i]]$cum.reclass.prob
tbl <- cbind(0, tbl)
assign("tmpvar", as.numeric(get(rcls.tbl[[i]]$variable)))
assign(pfac.1[i], sapply(tmpvar, cutsp, tbl))
assign(pfac.1[i], as.factor(get(pfac.1[i])))
}
}
mod2 <- eval(mod at call)
allb <- rbind(allb, coefficients(mod2))
}
rownames(allb) <- NULL
result$coeff.table <- allb
class(result) <- "perturb"
result
}
--
Austin Frank
http://aufrank.net
GPG Public Key (D7398C2F): http://aufrank.net/personal.asc
More information about the R-sig-mixed-models
mailing list