diff options
author | Ken Kellner <ken@kenkellner.com> | 2022-06-25 18:36:15 -0400 |
---|---|---|
committer | Ken Kellner <ken@kenkellner.com> | 2022-06-25 18:36:15 -0400 |
commit | a1f211529eb5e26f743a3bb08177ad8df231a4f4 (patch) | |
tree | abf9ecfe4881fa9c6424f174540232ff49d89d80 | |
parent | 0266f34e3a02003bed5f0f14ff91cb3e39f2fd59 (diff) |
Basic support for simulating random effects
-rw-r--r-- | R/power.R | 25 | ||||
-rw-r--r-- | R/simulate.R | 86 |
2 files changed, 86 insertions, 25 deletions
@@ -151,16 +151,38 @@ bootstrap_data <- function(data, nsims, design){ lapply(1:nsims, function(i) data[M_samps[[i]], J_samps[[i]]]) } -check_coefs <- function(coefs, fit, template=FALSE){ +check_coefs <- function(coefs, fit, formulas, template=FALSE){ required_subs <- names(fit@estimates@estimates) required_coefs <- lapply(fit@estimates@estimates, function(x) names(x@estimates)) required_lens <- lapply(required_coefs, length) + + # If there are random effects, adjust the expected coefficient names + # to remove the b vector and add the grouping covariate name + rand <- lapply(formulas, lme4::findbars) + if(!all(sapply(rand, is.null))){ + stopifnot(all(required_subs %in% names(formulas))) + rvar <- lapply(rand, function(x) unlist(lapply(x, all.vars))) + if(!all(sapply(rvar, length)<2)){ + stop("Only 1 random effect per parameter is supported", call.=FALSE) + } + for (i in required_subs){ + if(!is.null(rand[[i]][[1]])){ + signame <- rvar[[i]] + old_coefs <- required_coefs[[i]] + new_coefs <- old_coefs[!grepl("b_", old_coefs, fixed=TRUE)] + new_coefs <- c(new_coefs, signame) + required_coefs[[i]] <- new_coefs + } + } + } + dummy_coefs <- lapply(required_coefs, function(x){ out <- rep(0, length(x)) x <- gsub("(Intercept)", "intercept", x, fixed=TRUE) names(out) <- x out }) + if(template) return(dummy_coefs) if(is.null(coefs)){ @@ -226,6 +248,7 @@ check_coefs <- function(coefs, fit, template=FALSE){ } coefs[required_subs] } + wald <- function(est, se, null_hyp=NULL){ if(is.null(null_hyp) || is.na(null_hyp)) null_hyp <- 0 Z <- (est-null_hyp)/se diff --git a/R/simulate.R b/R/simulate.R index 3503ba5..7868948 100644 --- a/R/simulate.R +++ b/R/simulate.R @@ -59,6 +59,68 @@ blank_umFit <- function(fit_function){ } +setMethod("simulate", "character", + function(object, nsim=1, seed=NULL, formulas, coefs=NULL, design, guide=NULL, ...){ + model <- blank_umFit(object) + fit <- suppressWarnings(simulate_fit(model, formulas, guide, design, ...)) + coefs <- check_coefs(coefs, fit, formulas) + coefs <- generate_random_effects(coefs, fit, formulas) + fit <- replace_estimates(fit, coefs) + ysims <- simulate(fit, nsim) + umf <- fit@data + # fix this + umfs <- lapply(ysims, function(x){ + if(object=="occuMulti"){ + umf@ylist <- x + } else if(object=="gdistremoval"){ + umf@yDistance=x$yDistance + umf@yRemoval=x$yRemoval + } else { + umf@y <- x + } + umf + }) + if(length(umfs)==1) umfs <- umfs[[1]] + umfs +}) + + +generate_random_effects <- function(coefs, fit, formulas){ + required_subs <- names(fit@estimates@estimates) + rand <- lapply(formulas, lme4::findbars) + if(!all(sapply(rand, is.null))){ + rvar <- lapply(rand, function(x) unlist(lapply(x, all.vars))) + for (i in required_subs){ + if(!is.null(rand[[i]][[1]])){ + signame <- rvar[[i]] + old_coefs <- coefs[[i]] + new_coefs <- old_coefs[names(old_coefs)!=signame] + + # Find levels of factor variable + if(signame %in% names(siteCovs(fit@data))){ + lvldata <- siteCovs(fit@data)[[signame]] + } else if(signame %in% names(obsCovs(fit@data))){ + lvldata <- obsCovs(fit@data)[[signame]] + } else if(methods::.hasSlot(fit@data, "yearlySiteCovs") && signame %in% names(yearlySiteCovs(fit@data))){ + lvldata <- yearlySiteCovs(fit@data)[[signame]] + } else { + stop("Random effect covariate missing from data", call.=FALSE) + } + + if(!is.factor(lvldata)){ + stop("Random effect covariates must be specified as factors with guide argument", call.=FALSe) + } + b <- rnorm(length(levels(lvldata)), 0, old_coefs[signame]) + names(b) <- rep(paste0("b_",i), length(b)) + new_coefs <- c(new_coefs, b) + coefs[[i]] <- new_coefs + } + } + } + coefs +} + + setGeneric("get_umf_components", function(object, ...) standardGeneric("get_umf_components")) setMethod("get_umf_components", "unmarkedFit", @@ -103,30 +165,6 @@ setMethod("simulate_fit", "unmarkedFitOccuRN", }) -setMethod("simulate", "character", - function(object, nsim=1, seed=NULL, formulas, coefs=NULL, design, guide=NULL, ...){ - model <- blank_umFit(object) - fit <- suppressWarnings(simulate_fit(model, formulas, guide, design, ...)) - coefs <- check_coefs(coefs, fit) - fit <- replace_estimates(fit, coefs) - ysims <- simulate(fit, nsim) - umf <- fit@data - # fix this - umfs <- lapply(ysims, function(x){ - if(object=="occuMulti"){ - umf@ylist <- x - } else if(object=="gdistremoval"){ - umf@yDistance=x$yDistance - umf@yRemoval=x$yRemoval - } else { - umf@y <- x - } - umf - }) - if(length(umfs)==1) umfs <- umfs[[1]] - umfs -}) - setMethod("get_umf_components", "unmarkedFitMPois", function(object, formulas, guide, design, ...){ args <- list(...) |