https://github.com/cran/MuMIn
Tip revision: f8469f452d8a1be30d399d978de9550b4632bb51 authored by Kamil BartoĊ on 31 January 2012, 16:44:51 UTC
version 1.7.2
version 1.7.2
Tip revision: f8469f4
model-utils.R
# test for marginality constraints
`formulaAllowed` <-
function(frm, except = NULL) {
if(isTRUE(except)) return(TRUE)
factors <- attr(terms(frm), "factors")
if(length(factors) == 0L) return(TRUE)
ex <- rownames(factors)[apply(factors, 1L, function(x) any(x > 1L))]
if(is.character(except))
factors <- factors[!(rownames(factors) %in% except), ]
ret <- all(factors < 2L)
attr(ret, "marg.ex") <- ex
return(ret)
}
# Hidden functions
`.getLogLik` <- function()
if ("stats4" %in% loadedNamespaces())
stats4:::logLik else
stats::logLik
`.getCall` <- function(x) {
if(isS4(x)) {
if ("call" %in% slotNames(x)) slot(x, "call") else
NULL
} else {
if(!is.null(x$call)) {
x$call
} else if(!is.null(attr(x, "call"))) {
attr(x, "call")
} else
NULL
}
}
`.isREMLFit` <- function(x) {
if (inherits(x, "mer")) return (x@dims[["REML"]] != 0)
if (inherits(x, c("lme", "gls", "gam")) && !is.null(x$method))
return(x$method %in% c("lme.REML", "REML"))
if (any(inherits(x, c("lmer", "glmer"))))
return(x@status["REML"] != 0)
return(NA)
}
`.getRank` <- function(rank = NULL, rank.args = NULL, object = NULL, ...) {
rank.args <- c(rank.args, list(...))
if(is.null(rank)) {
IC <- as.function(c(alist(x=, do.call("AICc", list(x)))))
x <- NULL # just not to annoy R check
as.function(c(alist(x=, do.call("AICc", list(x)))))
attr(IC, "call") <- call("AICc", as.name("x"))
class(IC) <- c("function", "ICWithCall")
return(IC)
} else if(inherits(rank, "ICWithCall") && length(rank.args) == 0L) {
return(rank)
}
srank <- substitute(rank, parent.frame())
if(srank == "rank") srank <- substitute(rank)
rank <- match.fun(rank)
ICName <- switch(mode(srank), call=as.name("IC"), character=as.name(srank), name=, srank)
ICarg <- c(list(as.name("x")), rank.args)
ICCall <- as.call(c(ICName, ICarg))
IC <- as.function(c(alist(x=), list(substitute(do.call("rank", ICarg), list(ICarg=ICarg)))))
if(!is.null(object)) {
test <- IC(object)
if (!is.numeric(test) || length(test) != 1L)
stop("'rank' should return numeric vector of length 1")
}
attr(IC, "call") <- ICCall
class(IC) <- c("function", "ICWithCall")
IC
}
`matchCoef` <- function(m1, m2,
all.terms = getAllTerms(m2, intercept = TRUE),
beta = FALSE,
terms1 = getAllTerms(m1, intercept = TRUE),
coef1 = if (beta) beta.weights(m1)[, 3L] else coeffs(m1),
allCoef = FALSE
) {
if(any((terms1 %in% all.terms) == FALSE)) stop("'m1' is not nested within 'm2")
row <- structure(rep(NA, length(all.terms)), names = all.terms)
fxdCoefNames <- fixCoefNames(names(coef1))
row[terms1] <- NaN
pos <- match(terms1, fxdCoefNames, nomatch = 0L)
row[fxdCoefNames[pos]] <- coef1[pos]
if(allCoef) {
ct <- coefTable(m1)
rownames(ct)[match(names(coef1), rownames(ct))] <- fxdCoefNames
#rownames(ct) <- fxdCoefNames
attr(row, "coefTable") <- ct
}
row
}
# sorts alphabetically interaction components in model term names
# if 'peel', tries to remove coefficients wrapped into function-like syntax
# (this is meant mainly for 'unmarkedFit' models with names such as "psi(a:b:c)")
# TODO: this function is ugly, do something with it.
`fixCoefNames` <- function(x, sort = FALSE, peel = TRUE) {
if(!length(x)) return(x)
ox <- x
ia <- grep(":", x, fixed = TRUE)
if(!length(ia)) return(structure(x, order = rep.int(1, length(x))))
x <- ret <- x[ia]
if(peel) {
# case of pscl::hurdle, cf are prefixed with count_|zero_
if(all(substr(x, 1L, pos <- regexpr("_", x, fixed = TRUE)) %in%
c("count_", "zero_"))) {
ret <- substr(ret, pos + 1L, 256L)
k <- TRUE
suffix <- ""
} else { # unmarkedFit with its phi(...), lambda(...) etc...
k <- grepl("^\\w+\\(.+\\)$", x, perl = TRUE)
fname <- substring(x[k], 1L, attr(regexpr("^\\w+(?=\\()", x[k],
perl = TRUE),"match.length"))
# exclude common transformations
k[k] <- !(fname %in% c("log", "I", "exp", "s", "te"))
if(any(k)) {
pos <- vapply(x[k], function(z) {
parens <- lapply(lapply(c("(", ")"),
function(s) gregexpr(s, z, fixed = TRUE)[[1L]]),
function(y) y[y > 0L])
parseq <- unlist(parens, use.names = FALSE)
p <- cumsum(rep(c(1L, -1L), sapply(parens, length))[order(parseq)])
if(any(p[-length(p)] == 0L)) -1 else parseq[1L]
}, numeric(1L), USE.NAMES = FALSE)
k[k] <- pos != -1
pos <- pos[pos != -1]
if(any(k)) ret[k] <- substring(x[k], pos + 1L, nchar(x[k]) - 1L)
}
suffix <- ")"
}
} else k <- FALSE
ret <- vapply(lapply(spl <- strsplit(ret, ":"), base::sort), paste, "",
collapse = ":")
if(peel && any(k))
ret[k] <- paste(substring(x[k], 1L, pos), ret[k], suffix, sep = "")
ox[ia] <- ret
ord <- rep.int(1, length(ox))
ord[ia] <- sapply(spl, length)
structure(ox, order = ord)
}
#Tries to find out whether the models are fitted to the same data
.checkModels <- function(models, error = TRUE) {
#
cl <- sys.call(sys.parent())
err <- if (error) function(x) stop(simpleError(x, cl))
else function(x) warning(simpleWarning(x, cl))
res <- TRUE
responses <- lapply(models, function(x) {
f <- formula(x)
if((length(f) == 2L) || (is.call(f[[2L]]) && f[[2L]][[1L]] == "~")) 0 else f[[2L]]
})
if(!all(vapply(responses[-1L], "==", logical(1), responses[[1L]]))) {
err("response differs between models")
res <- FALSE
}
datas <- lapply(models, function(x) .getCall(x)$data)
# when using only 'nobs' - seems to be evaluated first outside of MuMIn namespace
# which e.g. gives an error in glmmML - the glmmML::nobs method is faulty.
nresid <- vapply(models, function(x) nobs(x), numeric(1L)) # , nall=TRUE
if(!all(datas[-1L] == datas[[1]]) || !all(nresid[-1L] == nresid[[1L]])) {
err("models are not all fitted to the same data")
res <- FALSE
}
invisible(res)
}
#system.time(for(i in 1:1000) abbreviateTerms(x))
`abbreviateTerms` <- function(x, n = 1L, capwords = FALSE, deflate = FALSE) {
if(deflate) dx <-
gsub("([\\(,]) *\\w+ *= *(~ *(1 *[\\+\\|]?)?)? *", "\\1", x, perl = TRUE)
else dx <- x
s <- strsplit(dx, "(?=[\\W_])", perl = TRUE)
# remove I(...):
s <- lapply(s, function(z) {
z <- if((n <- length(z)) > 3L && all(z[c(1L, 2L, n)] == c("I", "(", ")")))
z[3L:(n - 1L)] else z
z[z != " "]
})
v <- unique(unlist(s))
i <- grep("[[:alpha:]]", v, perl = FALSE)
av <- v
if(deflate) {
repl1 <- c("TRUE" = "T", "FALSE" = "F", "NULL" = "")
for(j in seq_along(repl1)) av[av == names(repl1)[j]] <- repl1[j]
}
av[i] <- abbreviate(av[i], n)
if(capwords) av[i] <- paste(toupper(substring(av[i], 1L, 1L)),
tolower(substring(av[i], 2L)), sep = "")
for(j in seq_along(s)) s[[j]] <- paste(av[match(s[[j]], v)], collapse = "")
names(av) <- v
structure(unlist(s), names = x, variables = av[i])
}
`model.names` <- function(object, ..., labels = NULL) {
if (missing(object) && length(models <- list(...)) > 0L) {
object <- models[[1L]]
} else if (inherits(object, "list")) {
if(length(object) == 0L) stop("at least one model must be given")
models <- object
object <- models[[1L]]
} else models <- list(object, ...)
if(length(models) == 0L) stop("at least one model must be given")
.modelNames(models = models, uqTerms = labels)
}
`.modelNames` <- function(models = NULL, allTerms, uqTerms, ...) {
if(missing(allTerms)) allTerms <- lapply(models, getAllTerms)
if(missing(uqTerms) || is.null(uqTerms))
uqTerms <- unique(unlist(allTerms, use.names = FALSE))
ret <- sapply(allTerms, function(x) paste(sort(match(x, uqTerms)),
collapse = ""))
dup <- table(ret)
dup <- dup[dup > 1L]
if(length(dup) > 0L) {
idup <- which(ret %in% names(dup))
ret[idup] <- sapply(idup, function(i) paste(ret[i],
letters[sum(ret[seq.int(i)] == ret[i])], sep=""))
}
ret[ret == ""] <- "(Null)"
attr(ret, "variables") <- structure(seq_along(uqTerms), names = uqTerms)
ret
}
`modelDescr` <- function(models, withModel = FALSE, withFamily = TRUE,
withArguments = TRUE, remove.cols = c("formula", "random", "fixed", "model",
"data", "family", "cluster")) {
if(withModel) {
allTermsList <- lapply(models, function(x) {
tt <- getAllTerms(x)
rtt <- attr(tt, "random.terms")
c(tt, if(!is.null(rtt)) paste("(", rtt, ")", sep = "") else NULL)
})
allTerms <- unique(unlist(allTermsList))
abvtt <- abbreviateTerms(allTerms)
variables <- attr(abvtt, "variables")
abvtt <- gsub("\\(1 \\| (\\S+)(?: %in%.*)?\\)", "(\\1)", abvtt, perl = TRUE)
abvtt <- sapply(allTermsList, function(x) paste(abvtt[match(x, allTerms)],
collapse = "+"))
} else abvtt <- variables <- NULL
if(withFamily) {
fam <- sapply(models, function(x) {
tryCatch(unlist(family(x)[c("family", "link")]),
error = function(e) c("", ""))
})
# remove default links
fam[2L, fam[2L, ] == sapply(unique(fam[1L, ]), function(x)
formals(get(x))$link)[fam[1L, ]]] <- NA
j <- !is.na(fam[2L,])
v <- fam[1L, ]
v[j] <- paste(fam[1L, j], "(", fam[2L, j], ")", sep="")
fam <- v
}
if(withArguments) {
cl <- lapply(models, .getCall)
arg <- lapply(cl, function(x) sapply(x[-1L], function(argval)
switch(mode(argval), character = , logical = argval,
numeric = signif(argval, 3L), deparse(argval, nlines = 1L))))
arg <- rbindDataFrameList(lapply(lapply(arg, t), as.data.frame))
arg <- cbind(class = as.factor(sapply(lapply(models, class), "[", 1L)),
arg[, !(colnames(arg) %in% remove.cols), drop = FALSE])
reml <- rep(NA, length(models))
if(!is.null(arg$method)) {
reml <- ((arg$class == "lme" &
is.na(arg$method)) | arg$method == "REML")
arg$method <- NULL
}
if(!is.null(arg$REML)) reml <- ifelse(is.na(arg$REML), reml, arg$REML == "TRUE")
arg$REML <- as.factor(reml)
arg <- as.matrix(arg)
arg[is.na(arg) | arg == "NULL"] <- ""
arg <- arg[, apply(arg, 2L, function(x) length(unique(x))) != 1L, drop = FALSE]
if(ncol(arg)) arg <- gsub("([\"'\\s]+|\\w+ *=)","", arg, perl = TRUE)
}
ret <- as.data.frame(cbind(model = abvtt, family = fam, arg, deparse.level = 0L))
attr(ret, "variables") <- variables
ret
}