Nothing
##' Tidying methods for TMB models
##'
##' @param x An object of class \code{TMB} (you may need to use
##' \code{class(obj) <- "TMB"} on your results from TMB)
##' @inheritParams glmmTMB_tidiers
##' @param effects which effects should be returned?
##' @param conf.method method for computing confidence intervals
##' @param ... additional arguments passed to confint function (tmbroot, tmbprofile)
##' @importFrom stats approx predict
##' @importFrom splines backSpline interpSpline
##' @importFrom furrr future_map_dfr
##' @importFrom forcats fct_inorder
## FIXME: retrieving stored objects doesn't work well ...
## but we also don't want to try compiling as part of example!
##' @examples
##' if (require("TMB")) {
##'
##' \dontrun{
##' runExample("simple",thisR=TRUE)
##' class(obj) <- "TMB"
##' tidy(obj,conf.int=TRUE,conf.method="wald")
##' }
##' \dontrun{tidy(obj,conf.int=TRUE,conf.method="uniroot")}
##' \dontrun{tidy(obj,conf.int=TRUE,conf.method="profile")}
##' }
##' @export
tidy.TMB <- function(x, effects = c("fixed", "random"),
conf.int = FALSE,
conf.level = 0.95,
conf.method = c("wald", "uniroot", "profile"), ...) {
assert_dependency("TMB")
## FIXME: implement CIs/profiling/etc. for random effects (and error out on a stub in the meantime)
## R CMD check/global variables
branch <- v <- param <- value <- zeta <- Estimate <- estimate <- std.error <- NULL
conf.method <- match.arg(conf.method)
sdr <- TMB::sdreport(x)
retlist <- list()
if ("fixed" %in% effects) {
ss <- summary(sdr, select = "fixed") %>%
as.data.frame() %>%
## FIXME: disambiguate repeated variable names better
## i.e. beta.1, beta.2 instead of beta, beta.1 ...
tibble::rownames_to_column("term") %>%
rename(estimate = Estimate, std.error = "Std. Error")
all_vars <- names(x$env$last.par.best)
if (!is.null(rnd <- x$env$random)) {
all_vars <- all_vars[-rnd]
}
if (conf.int) {
if (tolower(conf.method) == "wald") {
qval <- qnorm((1 + conf.level) / 2)
ss <- mutate(ss,
conf.low = estimate - qval * std.error,
conf.high = estimate + qval * std.error
)
} else if (conf.method == "uniroot") {
## FIXME: allow parm specs
## FIXME: avoid calling sdreport again inside tmbroot?
tt <- furrr::future_map_dfr(seq_along(all_vars),
~ TMB::tmbroot(x, ...))
ss <- mutate(ss,
conf.low = tt[["lwr"]],
conf.high = tt[["upr"]])
} else if (conf.method == "profile") {
## FIXME: allow parm specs
## FIXME: repeated var names?
## FIXME: tracing/quietly/etc?
prof0 <- furrr::future_map_dfr(seq_along(all_vars),
~ (TMB::tmbprofile(x,name=.,trace=FALSE)
%>% setNames(c("focal","value"))),
.id="param")
prof1 <- (prof0
%>% mutate(across(param, forcats::fct_inorder)) ## keep order consistent below!
%>% group_by(param)
%>% mutate(zeta=sqrt(2*(value-min(value))),
branch=ifelse(cumsum(zeta==0)<1, "lwr", "upr"))
%>% ungroup()
)
bad_prof_flag <- FALSE
critval <- qnorm((1+conf.level)/2)
interp_fun <- function(dd) {
bakspl <-tryCatch(backSpline(
forspl <- interpSpline(dd$focal, dd$zeta, na.action=na.omit)),
error=function(e)e)
if (inherits(bakspl, "error")) {
bad_prof_flag <<- TRUE ## set value globally
## may fail (if not at least two non-NA values ...)
res <- try(approx(dd$zeta, dd$focal, xout=critval)$y,
silent = TRUE)
if (inherits(res, "try-error")) {
res <- NA_real_
}
} else {
res <- predict(bakspl, critval)$y
}
return(res)
}
ttd <- (prof1
%>% group_by(param, branch)
%>% distinct()
%>% summarise(v=interp_fun(.data), .groups="drop")
)
tt <- (ttd %>% full_join(with(ttd, tidyr::crossing(param, branch)),
by = c("param", "branch"))
%>% arrange(branch, param)
)
ss$conf.low <- filter(tt, branch=="lwr") %>% pull(v)
ss$conf.high <- filter(tt, branch=="upr") %>% pull(v)
} else {
stop(sprintf("conf.method=%s not implemented", conf.method))
}
} ## if conf.int
} ## if 'fixed'
retlist$fixed <- ss
## FIXME: find a way to join rather than bind rows? (ordering fragility)
ret <- dplyr::bind_rows(retlist, .id = "type")
## FIXME: add statistic (mean/stderr)
## and p-value (2*pnorm(abs(statistic),lower.tail=FALSE))
## if requested
##
return(ret)
}
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.