diff --git a/DESCRIPTION b/DESCRIPTION index 929c66db8..b16d757e7 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Type: Package Package: parameters Title: Processing of Model Parameters -Version: 0.21.3.2 +Version: 0.21.3.3 Authors@R: c(person(given = "Daniel", family = "Lüdecke", @@ -146,6 +146,7 @@ Suggests: lme4, lmerTest, lmtest, + logistf, logspline, lqmm, M3C, diff --git a/NEWS.md b/NEWS.md index 58c32e1bd..778eb912a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -6,6 +6,11 @@ `marginaleffects::predictions()` now defaults to `FALSE`, in line with all the other `model_parameters()` methods. +## Changes + +* `model_parameters()` for models of package *survey* now gives informative + messages when `bootstrap = TRUE` (which is currently not supported). + # parameters 0.21.3 ## Changes diff --git a/R/1_model_parameters.R b/R/1_model_parameters.R index 0113673b7..aa8106750 100644 --- a/R/1_model_parameters.R +++ b/R/1_model_parameters.R @@ -576,14 +576,14 @@ model_parameters.default <- function(model, ci_method <- "quantile" } - args <- list( + fun_args <- list( model, iterations = iterations, ci = ci, ci_method = ci_method ) - args <- c(args, dots) - params <- do.call("bootstrap_parameters", args) + fun_args <- c(fun_args, dots) + params <- do.call("bootstrap_parameters", fun_args) # Processing, non-bootstrapped parameters } else { @@ -592,7 +592,7 @@ model_parameters.default <- function(model, ci_method <- "wald" } - args <- list( + fun_args <- list( model, ci = ci, component = component, @@ -607,8 +607,8 @@ model_parameters.default <- function(model, vcov = vcov, vcov_args = vcov_args ) - args <- c(args, dots) - params <- do.call(".extract_parameters_generic", args) + fun_args <- c(fun_args, dots) + params <- do.call(".extract_parameters_generic", fun_args) } @@ -686,12 +686,12 @@ model_parameters.glm <- function(model, # tell user that profiled CIs don't respect vcov-args if (identical(ci_method, "profile") && (!is.null(vcov) || !is.null(vcov_args)) && isTRUE(verbose)) { insight::format_alert( - "When `ci_method=\"profile\"`, `vcov` only modifies standard errors, test-statistic and p-values, but not confidence intervals.", + "When `ci_method=\"profile\"`, `vcov` only modifies standard errors, test-statistic and p-values, but not confidence intervals.", # nolint "Use `ci_method=\"wald\"` to return confidence intervals based on robust standard errors." ) } - args <- list( + fun_args <- list( model = model, ci = ci, ci_method = ci_method, @@ -708,8 +708,8 @@ model_parameters.glm <- function(model, vcov_args = vcov_args, verbose = verbose ) - args <- c(args, dots) - out <- do.call(".model_parameters_generic", args) + fun_args <- c(fun_args, dots) + out <- do.call(".model_parameters_generic", fun_args) attr(out, "object_name") <- insight::safe_deparse_symbol(substitute(model)) out diff --git a/R/3_p_value.R b/R/3_p_value.R index fca6d150e..a357443f2 100644 --- a/R/3_p_value.R +++ b/R/3_p_value.R @@ -105,13 +105,13 @@ p_value.default <- function(model, if (inherits(vcov, "data.frame") || "SE" %in% colnames(vcov)) { se <- vcov } else { - args <- list(model, + fun_args <- list(model, vcov_args = vcov_args, vcov = vcov, verbose = verbose ) - args <- c(args, dots) - se <- do.call("standard_error", args) + fun_args <- c(fun_args, dots) + se <- do.call("standard_error", fun_args) } dof <- degrees_of_freedom(model, method = "wald", verbose = FALSE) diff --git a/R/4_standard_error.R b/R/4_standard_error.R index e6b1e5d46..6dc4b0292 100644 --- a/R/4_standard_error.R +++ b/R/4_standard_error.R @@ -88,8 +88,8 @@ standard_error.default <- function(model, # vcov: function which returns a matrix if (is.function(vcov)) { - args <- c(list(model), vcov_args, dots) - se <- .safe(sqrt(diag(do.call("vcov", args)))) + fun_args <- c(list(model), vcov_args, dots) + se <- .safe(sqrt(diag(do.call("vcov", fun_args)))) } # vcov: character (with backward compatibility for `robust = TRUE`) diff --git a/R/ci_profile_boot.R b/R/ci_profile_boot.R index 0dab03861..6dfc4bbb2 100644 --- a/R/ci_profile_boot.R +++ b/R/ci_profile_boot.R @@ -84,14 +84,14 @@ dot_args <- .check_profile_uniroot_args(...) if (is.null(profiled)) { - args <- list(x, method = "profile", level = ci, dot_args) - out <- as.data.frame(do.call(stats::confint, args)) + fun_args <- list(x, method = "profile", level = ci, dot_args) + out <- as.data.frame(do.call(stats::confint, fun_args)) } else { - args <- list(profiled, level = ci, dot_args) - out <- .safe(as.data.frame(do.call(stats::confint, args))) + fun_args <- list(profiled, level = ci, dot_args) + out <- .safe(as.data.frame(do.call(stats::confint, fun_args))) if (is.null(out)) { - args <- list(x, method = "profile", level = ci, dot_args) - out <- as.data.frame(do.call(stats::confint, args)) + fun_args <- list(x, method = "profile", level = ci, dot_args) + out <- as.data.frame(do.call(stats::confint, fun_args)) } } .process_glmmTMB_CI(x, out, ci, component) @@ -103,8 +103,8 @@ .ci_uniroot_glmmTMB <- function(x, ci, component, ...) { # make sure "..." doesn't pass invalid arguments to package TMB dot_args <- .check_profile_uniroot_args(...) - args <- list(x, level = ci, method = "uniroot", dot_args) - out <- as.data.frame(do.call(stats::confint, args)) + fun_args <- list(x, level = ci, method = "uniroot", dot_args) + out <- as.data.frame(do.call(stats::confint, fun_args)) .process_glmmTMB_CI(x, out, ci, component) } diff --git a/R/dominance_analysis.R b/R/dominance_analysis.R index 90d991ecb..efeb46e59 100644 --- a/R/dominance_analysis.R +++ b/R/dominance_analysis.R @@ -347,11 +347,10 @@ dominance_analysis <- function(model, sets = NULL, all = NULL, # quote arguments for domin for (arg in quote_args) { - if (!(arg %in% names(args))) { - insight::format_error(arg, " in `quote_args` not among arguments in model.") + if (arg %in% names(args)) { + args[[arg]] <- str2lang(paste0("quote(", deparse(args[[arg]]), ")", collapse = "")) } else { - args[[arg]] <- - str2lang(paste0("quote(", deparse(args[[arg]]), ")", collapse = "")) + insight::format_error(arg, " in `quote_args` not among arguments in model.") } } diff --git a/R/extract_parameters.R b/R/extract_parameters.R index 61411246c..997e75938 100644 --- a/R/extract_parameters.R +++ b/R/extract_parameters.R @@ -43,12 +43,11 @@ # ==== for refit, we completely refit the model, than extract parameters, ci etc. as usual if (isTRUE(standardize == "refit")) { - args <- list(model, verbose = FALSE) - args <- c(args, list(...)) + fun_args <- c(list(model, verbose = FALSE), dots) # argument name conflict with deprecated `robust` - args[["robust"]] <- NULL + fun_args[["robust"]] <- NULL fun <- datawizard::standardize - model <- do.call(fun, args) + model <- do.call(fun, fun_args) } parameters <- insight::get_parameters(model, @@ -80,7 +79,7 @@ # intercepts (alpha-coefficients) in the component column if (inherits(model, "polr")) { - intercept_groups <- which(grepl("Intercept:", parameters$Parameter, fixed = TRUE)) + intercept_groups <- grep("Intercept:", parameters$Parameter, fixed = TRUE) parameters$Parameter <- gsub("Intercept: ", "", parameters$Parameter, fixed = TRUE) } else if (inherits(model, "clm") && !is.null(model$alpha)) { intercept_groups <- rep( @@ -104,21 +103,25 @@ # ==== CI - only if we don't already have CI for std. parameters - if (!is.null(ci)) { - args <- list(model, + if (is.null(ci)) { + ci_cols <- NULL + } else { + fun_args <- list(model, ci = ci, component = component, vcov = vcov, vcov_args = vcov_args, verbose = verbose ) - args <- c(args, dots) + fun_args <- c(fun_args, dots) if (!is.null(ci_method)) { - args[["method"]] <- ci_method + fun_args[["method"]] <- ci_method } - ci_df <- suppressMessages(do.call("ci", args)) + ci_df <- suppressMessages(do.call("ci", fun_args)) - if (!is.null(ci_df)) { + if (is.null(ci_df)) { + ci_cols <- NULL + } else { # for multiple CI columns, reshape CI-dataframe to match parameters df if (length(ci) > 1) { ci_df <- datawizard::reshape_ci(ci_df) @@ -126,17 +129,13 @@ # remember names of CI columns, used for later sorting of columns ci_cols <- names(ci_df)[!names(ci_df) %in% c("CI", merge_by)] parameters <- merge(parameters, ci_df, by = merge_by, sort = FALSE) - } else { - ci_cols <- NULL } - } else { - ci_cols <- NULL } # ==== p value - args <- list(model, + fun_args <- list(model, method = ci_method, effects = effects, verbose = verbose, @@ -144,8 +143,8 @@ vcov = vcov, vcov_args = vcov_args ) - args <- c(args, dots) - pval <- do.call("p_value", args) + fun_args <- c(fun_args, dots) + pval <- do.call("p_value", fun_args) if (!is.null(pval)) { parameters <- merge(parameters, pval, by = merge_by, sort = FALSE) @@ -155,18 +154,18 @@ # ==== standard error - only if we don't already have SE for std. parameters std_err <- NULL - args <- list(model, + fun_args <- list(model, effects = effects, component = component, verbose = verbose, vcov = vcov, vcov_args = vcov_args ) - args <- c(args, dots) + fun_args <- c(fun_args, dots) if (!is.null(ci_method)) { - args[["method"]] <- ci_method + fun_args[["method"]] <- ci_method } - std_err <- do.call("standard_error", args) + std_err <- do.call("standard_error", fun_args) if (!is.null(std_err)) { parameters <- merge(parameters, std_err, by = merge_by, sort = FALSE) @@ -186,10 +185,10 @@ # ==== degrees of freedom - if (!is.null(ci_method)) { - df_error <- degrees_of_freedom(model, method = ci_method, verbose = FALSE) - } else { + if (is.null(ci_method)) { df_error <- degrees_of_freedom(model, method = "any", verbose = FALSE) + } else { + df_error <- degrees_of_freedom(model, method = ci_method, verbose = FALSE) } if (!is.null(df_error) && (length(df_error) == 1 || length(df_error) == nrow(parameters))) { if (length(df_error) == 1) { @@ -232,8 +231,8 @@ # ==== remove Component column if not needed - if (!is.null(parameters$Component) && insight::n_unique(parameters$Component) == 1 && !keep_component_column) parameters$Component <- NULL - if ((!is.null(parameters$Effects) && insight::n_unique(parameters$Effects) == 1) || effects == "fixed") parameters$Effects <- NULL + if (!is.null(parameters$Component) && insight::n_unique(parameters$Component) == 1 && !keep_component_column) parameters$Component <- NULL # nolint + if ((!is.null(parameters$Effects) && insight::n_unique(parameters$Effects) == 1) || effects == "fixed") parameters$Effects <- NULL # nolint # ==== filter parameters, if requested @@ -383,16 +382,16 @@ } # row to keep and drop - if (!is.null(keep)) { - rows_to_keep <- grepl(keep, params[[column]], perl = TRUE) - } else { + if (is.null(keep)) { rows_to_keep <- rep_len(TRUE, nrow(params)) + } else { + rows_to_keep <- grepl(keep, params[[column]], perl = TRUE) } - if (!is.null(drop)) { - rows_to_drop <- !grepl(drop, params[[column]], perl = TRUE) - } else { + if (is.null(drop)) { rows_to_drop <- rep_len(TRUE, nrow(params)) + } else { + rows_to_drop <- !grepl(drop, params[[column]], perl = TRUE) } @@ -401,7 +400,7 @@ if (nrow(out) == 0) { if (verbose) { insight::format_alert( - "The pattern defined in the `keep` (and `drop`) arguments would remove all parameters from the output. Thus, selecting specific parameters will be ignored." + "The pattern defined in the `keep` (and `drop`) arguments would remove all parameters from the output. Thus, selecting specific parameters will be ignored." # nolint ) } return(params) @@ -452,33 +451,35 @@ # Degrees of freedom if (.dof_method_ok(model, ci_method)) { - df <- degrees_of_freedom(model, method = ci_method, verbose = FALSE) + dof <- degrees_of_freedom(model, method = ci_method, verbose = FALSE) } else { - df <- Inf + dof <- Inf } df_error <- data.frame( Parameter = parameters$Parameter, - df_error = as.vector(df), + df_error = as.vector(dof), stringsAsFactors = FALSE ) # for KR-dof, we have the SE as well, to save computation time - df_error$SE <- attr(df, "se", exact = TRUE) + df_error$SE <- attr(dof, "se", exact = TRUE) # CI - only if we don't already have CI for std. parameters - if (!is.null(ci)) { + if (is.null(ci)) { + ci_cols <- NULL + } else { # robust (current or deprecated) if (!is.null(vcov) || isTRUE(list(...)[["robust"]])) { - args <- list(model, + fun_args <- list(model, ci = ci, vcov = vcov, vcov_args = vcov_args, verbose = verbose ) - args <- c(args, dots) - ci_df <- suppressMessages(do.call("ci", args)) + fun_args <- c(fun_args, dots) + ci_df <- suppressMessages(do.call("ci", fun_args)) } else if (ci_method %in% c("kenward", "kr")) { # special handling for KR-CIs, where we already have computed SE ci_df <- .ci_kenward_dof(model, ci = ci, df_kr = df_error) @@ -488,21 +489,19 @@ if (length(ci) > 1) ci_df <- datawizard::reshape_ci(ci_df) ci_cols <- names(ci_df)[!names(ci_df) %in% c("CI", "Parameter")] parameters <- merge(parameters, ci_df, by = "Parameter", sort = FALSE) - } else { - ci_cols <- NULL } # standard error - only if we don't already have SE for std. parameters if (!"SE" %in% colnames(parameters)) { if (!is.null(vcov) || isTRUE(dots[["robust"]])) { - args <- list(model, + fun_args <- list(model, vcov = vcov, vcov_args = vcov_args, verbose = verbose ) - args <- c(args, dots) - parameters <- merge(parameters, do.call("standard_error", args), by = "Parameter", sort = FALSE) + fun_args <- c(fun_args, dots) + parameters <- merge(parameters, do.call("standard_error", fun_args), by = "Parameter", sort = FALSE) # special handling for KR-SEs, which we already have computed from dof } else if ("SE" %in% colnames(df_error)) { se_kr <- df_error @@ -521,13 +520,13 @@ # p value if (!is.null(vcov) || isTRUE(list(...)[["robust"]])) { - args <- list(model, + fun_args <- list(model, vcov = vcov, vcov_args = vcov_args, verbose = verbose ) - args <- c(args, dots) - parameters <- merge(parameters, do.call("p_value", args), by = "Parameter", sort = FALSE) + fun_args <- c(fun_args, dots) + parameters <- merge(parameters, do.call("p_value", fun_args), by = "Parameter", sort = FALSE) } else { if ("Pr(>|z|)" %in% names(parameters)) { names(parameters)[grepl("Pr(>|z|)", names(parameters), fixed = TRUE)] <- "p" @@ -543,7 +542,7 @@ } else { parameters <- merge( parameters, - p_value(model, dof = df, effects = "fixed"), + p_value(model, dof = dof, effects = "fixed"), by = "Parameter", sort = FALSE ) @@ -635,8 +634,8 @@ } # Reorder - order <- c("Parameter", coef_col, "SE", ci_cols, "t", "z", "df", "df_error", "p", "Component") - parameters <- parameters[order[order %in% names(parameters)]] + col_order <- c("Parameter", coef_col, "SE", ci_cols, "t", "z", "df", "df_error", "p", "Component") + parameters <- parameters[col_order[col_order %in% names(parameters)]] # add sigma @@ -765,7 +764,23 @@ verbose = verbose, ... ) - } else if (!is.null(standardize)) { + } else if (is.null(standardize)) { + parameters <- bayestestR::describe_posterior( + model, + centrality = centrality, + dispersion = dispersion, + ci = ci, + ci_method = ci_method, + test = test, + rope_range = rope_range, + rope_ci = rope_ci, + bf_prior = bf_prior, + diagnostic = diagnostic, + priors = priors, + verbose = verbose, + ... + ) + } else { parameters <- bayestestR::describe_posterior( model, centrality = centrality, @@ -804,22 +819,6 @@ parameters[c("Parameter", setdiff(colnames(parameters), colnames(std_parameters)))], sort = FALSE ) - } else { - parameters <- bayestestR::describe_posterior( - model, - centrality = centrality, - dispersion = dispersion, - ci = ci, - ci_method = ci_method, - test = test, - rope_range = rope_range, - rope_ci = rope_ci, - bf_prior = bf_prior, - diagnostic = diagnostic, - priors = priors, - verbose = verbose, - ... - ) } if (length(ci) > 1) { @@ -886,7 +885,7 @@ if (!is.logical(standardize) && !(standardize %in% valid_std_options)) { if (verbose) { insight::format_alert( - "`standardize` should be one of `TRUE`, \"all\", \"std.all\", \"latent\", \"std.lv\", \"no_exogenous\" or \"std.nox\".", + "`standardize` should be one of `TRUE`, \"all\", \"std.all\", \"latent\", \"std.lv\", \"no_exogenous\" or \"std.nox\".", # nolint "Returning unstandardized solution." ) } @@ -928,7 +927,7 @@ )] # Get estimates - data <- do.call( + sem_data <- do.call( lavaan::parameterEstimates, c( list(object = model, se = TRUE, ci = TRUE, level = ci), @@ -936,7 +935,7 @@ ) ) - label <- data$label + label <- sem_data$label # check if standardized estimates are requested, and if so, which type if (isTRUE(standardize) || !is.logical(standardize)) { @@ -958,23 +957,23 @@ valid <- names(formals(lavaan::standardizedsolution)) dots <- list(...) dots <- dots[names(dots) %in% valid] - args <- c(list(model, se = TRUE, level = ci, type = type), dots) + fun_args <- c(list(model, se = TRUE, level = ci, type = type), dots) f <- utils::getFromNamespace("standardizedsolution", "lavaan") - data <- do.call("f", args) - names(data)[names(data) == "est.std"] <- "est" + sem_data <- do.call("f", fun_args) + names(sem_data)[names(sem_data) == "est.std"] <- "est" } params <- data.frame( - To = data$lhs, - Operator = data$op, - From = data$rhs, - Coefficient = data$est, - SE = data$se, - CI_low = data$ci.lower, - CI_high = data$ci.upper, - z = data$z, - p = data$pvalue, + To = sem_data$lhs, + Operator = sem_data$op, + From = sem_data$rhs, + Coefficient = sem_data$est, + SE = sem_data$se, + CI_low = sem_data$ci.lower, + CI_high = sem_data$ci.upper, + z = sem_data$z, + p = sem_data$pvalue, stringsAsFactors = FALSE ) @@ -995,8 +994,8 @@ params$p[is.na(params$p)] <- 0 } - if ("group" %in% names(data)) { - params$Group <- data$group + if ("group" %in% names(sem_data)) { + params$Group <- sem_data$group } # filter parameters, if requested diff --git a/R/methods_betareg.R b/R/methods_betareg.R index dbc8451ac..4c4ce273b 100644 --- a/R/methods_betareg.R +++ b/R/methods_betareg.R @@ -32,7 +32,7 @@ model_parameters.betareg <- function(model, ## TODO check merge by - args <- list( + fun_args <- list( model, ci = ci, component = component, @@ -48,9 +48,9 @@ model_parameters.betareg <- function(model, vcov = NULL, vcov_args = NULL ) - args <- c(args, dot_args) + fun_args <- c(fun_args, dot_args) - out <- do.call(".model_parameters_generic", args) + out <- do.call(".model_parameters_generic", fun_args) attr(out, "object_name") <- insight::safe_deparse_symbol(substitute(model)) out } diff --git a/R/methods_brglm2.R b/R/methods_brglm2.R index 2b6c0cdf2..2b9eb4ca9 100644 --- a/R/methods_brglm2.R +++ b/R/methods_brglm2.R @@ -45,7 +45,7 @@ model_parameters.bracl <- function(model, merge_by <- "Parameter" } - args <- list( + fun_args <- list( model, ci = ci, bootstrap = bootstrap, @@ -60,9 +60,9 @@ model_parameters.bracl <- function(model, vcov = NULL, vcov_args = NULL ) - args <- c(args, dot_args) + fun_args <- c(fun_args, dot_args) - out <- do.call(".model_parameters_generic", args) + out <- do.call(".model_parameters_generic", fun_args) attr(out, "object_name") <- insight::safe_deparse_symbol(substitute(model)) out } @@ -198,22 +198,22 @@ degrees_of_freedom.nnet <- degrees_of_freedom.multinom standard_error.multinom <- function(model, ...) { se <- tryCatch( { - stderr <- summary(model)$standard.errors - if (is.null(stderr)) { + std_err <- summary(model)$standard.errors + if (is.null(std_err)) { vc <- insight::get_varcov(model) - stderr <- as.vector(sqrt(diag(vc))) + std_err <- as.vector(sqrt(diag(vc))) } else { - if (is.matrix(stderr)) { + if (is.matrix(std_err)) { tmp <- NULL - for (i in seq_len(nrow(stderr))) { - tmp <- c(tmp, as.vector(stderr[i, ])) + for (i in seq_len(nrow(std_err))) { + tmp <- c(tmp, as.vector(std_err[i, ])) } } else { - tmp <- as.vector(stderr) + tmp <- as.vector(std_err) } - stderr <- tmp + std_err <- tmp } - stderr + std_err }, error = function(e) { vc <- insight::get_varcov(model) @@ -257,9 +257,9 @@ simulate_parameters.multinom <- function(model, ci_method = "quantile", test = "p-value", ...) { - data <- simulate_model(model, iterations = iterations, ...) + sim_data <- simulate_model(model, iterations = iterations, ...) out <- .summary_bootstrap( - data = data, + data = sim_data, test = test, centrality = centrality, ci = ci, diff --git a/R/methods_car.R b/R/methods_car.R index 1de7f01c6..0284cb283 100644 --- a/R/methods_car.R +++ b/R/methods_car.R @@ -3,7 +3,7 @@ model_parameters.deltaMethod <- function(model, p_adjust = NULL, verbose = TRUE, dots <- list(...) if ("ci" %in% names(dots)) { insight::format_warning( - "The `ci` argument is not supported by `model_parameters` for objects of this class. Use the `level` argument of the `deltaMethod` function instead." + "The `ci` argument is not supported by `model_parameters` for objects of this class. Use the `level` argument of the `deltaMethod` function instead." # nolint ) dots[["ci"]] <- NULL } @@ -37,7 +37,7 @@ model_parameters.deltaMethod <- function(model, p_adjust = NULL, verbose = TRUE, params <- .p_adjust(params, p_adjust, model, verbose) } - args <- list( + fun_args <- list( params, model, ci = ci, @@ -49,9 +49,9 @@ model_parameters.deltaMethod <- function(model, p_adjust = NULL, verbose = TRUE, summary = FALSE, verbose = verbose ) - args <- c(args, dots) + fun_args <- c(fun_args, dots) - params <- do.call(".add_model_parameters_attributes", args) + params <- do.call(".add_model_parameters_attributes", fun_args) class(params) <- c("parameters_model", "see_parameters_model", class(params)) attr(params, "object_name") <- insight::safe_deparse_symbol(substitute(model)) diff --git a/R/methods_cgam.R b/R/methods_cgam.R index 661dbf2e4..a70416cd2 100644 --- a/R/methods_cgam.R +++ b/R/methods_cgam.R @@ -60,7 +60,7 @@ model_parameters.cgam <- function(model, ... ) } else { - args <- list( + fun_args <- list( model, ci = ci, ci_method = ci_method, @@ -74,8 +74,8 @@ model_parameters.cgam <- function(model, vcov = NULL, vcov_args = NULL ) - args <- c(args, dot_args) - params <- do.call(".extract_parameters_generic", args) + fun_args <- c(fun_args, dot_args) + params <- do.call(".extract_parameters_generic", fun_args) } # fix statistic column @@ -84,7 +84,7 @@ model_parameters.cgam <- function(model, } # fix estimated df column - if (inherits(model, c("gam", "cgam", "scam", "rqss")) && "smooth_terms" %in% params$Component && !("df" %in% names(params))) { + if (inherits(model, c("gam", "cgam", "scam", "rqss")) && "smooth_terms" %in% params$Component && !("df" %in% names(params))) { # nolint params$df <- params$Coefficient params$df[params$Component != "smooth_terms"] <- NA params$df_error[params$Component == "smooth_terms"] <- NA diff --git a/R/methods_glmmTMB.R b/R/methods_glmmTMB.R index 9738c947b..ccef7de94 100644 --- a/R/methods_glmmTMB.R +++ b/R/methods_glmmTMB.R @@ -81,7 +81,7 @@ model_parameters.glmmTMB <- function(model, } } } else { - args <- list( + fun_args <- list( model, ci = ci, component = component, @@ -100,8 +100,8 @@ model_parameters.glmmTMB <- function(model, wb_component = wb_component, summary = summary ) - args <- c(args, dot_args) - params <- do.call(".extract_parameters_generic", args) + fun_args <- c(fun_args, dot_args) + params <- do.call(".extract_parameters_generic", fun_args) } # add dispersion parameter @@ -131,7 +131,7 @@ model_parameters.glmmTMB <- function(model, if (verbose) { insight::format_alert( "Cannot compute standard errors and confidence intervals for sigma parameter.", - "Your model may suffer from singularity (see '?lme4::isSingular' and '?performance::check_singularity')." + "Your model may suffer from singularity (see '?lme4::isSingular' and '?performance::check_singularity')." # nolint ) } c(NA, NA) @@ -157,7 +157,7 @@ model_parameters.glmmTMB <- function(model, params_random <- .extract_random_parameters(model, ci = ci, effects = effects, component = component) if (length(random_effects) > 1) { insight::format_alert( - "Cannot extract confidence intervals for random variance parameters from models with more than one grouping factor." + "Cannot extract confidence intervals for random variance parameters from models with more than one grouping factor." # nolint ) } } else { @@ -173,12 +173,12 @@ model_parameters.glmmTMB <- function(model, # remove redundant dispersion parameter if (isTRUE(dispersion_param) && !is.null(params) && !is.null(params$Component)) { disp <- which(params$Component == "dispersion") - resid <- which(params_variance$Group == "Residual") + res <- which(params_variance$Group == "Residual") # check if we have dispersion parameter, and either no sigma # or sigma equals dispersion if (length(disp) > 0 && - length(resid) > 0 && - isTRUE(all.equal(params_variance$Coefficient[resid], + length(res) > 0 && + isTRUE(all.equal(params_variance$Coefficient[res], params$Coefficient[disp], tolerance = 1e-5 ))) { @@ -202,10 +202,10 @@ model_parameters.glmmTMB <- function(model, } # reorder - if (!is.null(params_random)) { - params <- params[match(colnames(params_random), colnames(params))] - } else { + if (is.null(params_random)) { params <- params[match(colnames(params_variance), colnames(params))] + } else { + params <- params[match(colnames(params_random), colnames(params))] } } @@ -466,16 +466,15 @@ simulate_parameters.glmmTMB <- function(model, ci_method = "quantile", test = "p-value", ...) { - data <- simulate_model(model, iterations = iterations, ...) - out <- - .summary_bootstrap( - data = data, - test = test, - centrality = centrality, - ci = ci, - ci_method = ci_method, - ... - ) + sim_data <- simulate_model(model, iterations = iterations, ...) + out <- .summary_bootstrap( + data = sim_data, + test = test, + centrality = centrality, + ci = ci, + ci_method = ci_method, + ... + ) params <- insight::get_parameters(model, ...) if ("Effects" %in% colnames(params) && insight::n_unique(params$Effects) > 1) { diff --git a/R/methods_hglm.R b/R/methods_hglm.R index beb24306d..4f237e112 100644 --- a/R/methods_hglm.R +++ b/R/methods_hglm.R @@ -223,13 +223,13 @@ p_value.hglm <- function(model, ...) { dots <- list(...) dots$component <- NULL - args <- list( + fun_args <- list( model, dof = dof, component = "conditional", method = method, verbose = verbose ) - args <- c(args, dots) - do.call("p_value.default", args) + fun_args <- c(fun_args, dots) + do.call("p_value.default", fun_args) } diff --git a/R/methods_lme4.R b/R/methods_lme4.R index 549317ef4..ee1bcd537 100644 --- a/R/methods_lme4.R +++ b/R/methods_lme4.R @@ -197,7 +197,7 @@ model_parameters.merMod <- function(model, } } } else { - args <- list( + fun_args <- list( model, ci = ci, ci_method = ci_method, @@ -212,8 +212,8 @@ model_parameters.merMod <- function(model, vcov = vcov, vcov_args = vcov_args ) - args <- c(args, dots) - params <- do.call(".extract_parameters_mixed", args) + fun_args <- c(fun_args, dots) + params <- do.call(".extract_parameters_mixed", fun_args) } params$Effects <- "fixed" @@ -244,10 +244,10 @@ model_parameters.merMod <- function(model, params$Level <- NA params$Group <- "" - if (!is.null(params_random)) { - params <- params[match(colnames(params_random), colnames(params))] - } else { + if (is.null(params_random)) { params <- params[match(colnames(params_variance), colnames(params))] + } else { + params <- params[match(colnames(params_random), colnames(params))] } } @@ -348,12 +348,12 @@ standard_error.merMod <- function(model, } if (!is.null(vcov) || isTRUE(dots[["robust"]])) { - args <- list(model, + fun_args <- list(model, vcov = vcov, vcov_args = vcov_args ) - args <- c(args, dots) - out <- do.call("standard_error.default", args) + fun_args <- c(fun_args, dots) + out <- do.call("standard_error.default", fun_args) return(out) } diff --git a/R/methods_logistf.R b/R/methods_logistf.R index 2912c488b..27f47562e 100644 --- a/R/methods_logistf.R +++ b/R/methods_logistf.R @@ -49,7 +49,7 @@ p_value.logistf <- function(model, ...) { utils::capture.output(s <- summary(model)) # nolint .data_frame( - Parameter = .remove_backticks_from_string(names(s$prob)), + Parameter = .remove_backticks_from_string(names(s$coefficients)), p = as.vector(s$prob) ) } diff --git a/R/methods_mice.R b/R/methods_mice.R index 3f0511b9f..cdf326399 100644 --- a/R/methods_mice.R +++ b/R/methods_mice.R @@ -108,7 +108,7 @@ model_parameters.mipo <- function(model, merge_by <- "Parameter" } - args <- list( + fun_args <- list( model, ci = ci, merge_by = merge_by, @@ -119,9 +119,9 @@ model_parameters.mipo <- function(model, vcov = NULL, vcov_args = NULL ) - args <- c(args, dot_args) + fun_args <- c(fun_args, dot_args) - out <- do.call(".model_parameters_generic", args) + out <- do.call(".model_parameters_generic", fun_args) attr(out, "object_name") <- insight::safe_deparse_symbol(substitute(model)) out } diff --git a/R/methods_nestedLogit.R b/R/methods_nestedLogit.R index 7cf670ded..90bc86169 100644 --- a/R/methods_nestedLogit.R +++ b/R/methods_nestedLogit.R @@ -45,12 +45,12 @@ model_parameters.nestedLogit <- function(model, # tell user that profiled CIs don't respect vcov-args if (identical(ci_method, "profile") && (!is.null(vcov) || !is.null(vcov_args)) && isTRUE(verbose)) { insight::format_alert( - "When `ci_method=\"profile\"`, `vcov` only modifies standard errors, test-statistic and p-values, but not confidence intervals.", + "When `ci_method=\"profile\"`, `vcov` only modifies standard errors, test-statistic and p-values, but not confidence intervals.", # nolint "Use `ci_method=\"wald\"` to return confidence intervals based on robust standard errors." ) } - args <- list( + fun_args <- list( model = model, ci = ci, ci_method = ci_method, @@ -67,8 +67,8 @@ model_parameters.nestedLogit <- function(model, vcov = vcov, vcov_args = vcov_args ) - args <- c(args, dots) - out <- do.call(".model_parameters_generic", args) + fun_args <- c(fun_args, dots) + out <- do.call(".model_parameters_generic", fun_args) attr(out, "object_name") <- insight::safe_deparse_symbol(substitute(model)) out @@ -89,19 +89,17 @@ degrees_of_freedom.nestedLogit <- function(model, dof <- rep(vapply(model$models, stats::df.residual, numeric(1)), each = nrow(cf)) if (!is.null(component) && !identical(component, "all")) { comp <- intersect(names(dof), component) - if (!length(comp)) { + if (length(comp)) { + dof <- dof[comp] + } else { if (verbose) { - insight::format_alert( - paste0( - "No matching model found. Possible values for `component` are ", - toString(paste0("'", names(model$models), "'")), - "." - ) - ) + insight::format_alert(paste0( + "No matching model found. Possible values for `component` are ", + toString(paste0("'", names(model$models), "'")), + "." + )) } dof <- Inf - } else { - dof <- dof[comp] } } } else { @@ -128,8 +126,8 @@ standard_error.nestedLogit <- function(model, # vcov: function which returns a matrix if (is.function(vcov)) { - args <- c(list(model), vcov_args, dots) - se <- .safe(sqrt(diag(do.call("vcov", args)))) + fun_args <- c(list(model), vcov_args, dots) + se <- .safe(sqrt(diag(do.call("vcov", fun_args)))) } # vcov: character (with backward compatibility for `robust = TRUE`) @@ -182,7 +180,11 @@ p_value.nestedLogit <- function(model, vcov_args = NULL, verbose = TRUE, ...) { - if (!is.null(vcov)) { + if (is.null(vcov)) { + p <- as.vector(as.data.frame(do.call(rbind, lapply(model$models, function(i) { + stats::coef(summary(i)) + })))[, "Pr(>|z|)"]) + } else { p <- p_value.default( model, dof = dof, @@ -193,10 +195,6 @@ p_value.nestedLogit <- function(model, verbose = verbose, ... )[["p"]] - } else { - p <- as.vector(as.data.frame(do.call(rbind, lapply(model$models, function(i) { - stats::coef(summary(i)) - })))[, "Pr(>|z|)"]) } params <- insight::get_parameters(model, component = component) @@ -267,8 +265,8 @@ simulate_model.nestedLogit <- function(model, iterations = 1000, ...) { out <- lapply(unique(params$Component), function(i) { pars <- params[params$Component == i, ] - beta <- stats::setNames(pars$Estimate, pars$Parameter) - d <- as.data.frame(.mvrnorm(n = iterations, mu = beta, Sigma = varcov[[i]])) + betas <- stats::setNames(pars$Estimate, pars$Parameter) + d <- as.data.frame(.mvrnorm(n = iterations, mu = betas, Sigma = varcov[[i]])) d$Component <- i d }) @@ -289,10 +287,10 @@ simulate_parameters.nestedLogit <- function(model, ci_method = "quantile", test = "p-value", ...) { - data <- simulate_model(model, iterations = iterations, ...) + sim_data <- simulate_model(model, iterations = iterations, ...) - out <- lapply(unique(data$Component), function(i) { - pars <- data[data$Component == i, ] + out <- lapply(unique(sim_data$Component), function(i) { + pars <- sim_data[sim_data$Component == i, ] d <- .summary_bootstrap( data = pars, test = test, diff --git a/R/methods_plm.R b/R/methods_plm.R index 109fa53ba..00a120df9 100644 --- a/R/methods_plm.R +++ b/R/methods_plm.R @@ -27,8 +27,8 @@ standard_error.plm <- function(model, vcov = NULL, vcov_args = NULL, verbose = T # vcov: function which returns a matrix if (is.function(vcov)) { - args <- c(list(model), vcov_args, dots) - se <- .safe(sqrt(diag(do.call("vcov", args)))) + fun_args <- c(list(model), vcov_args, dots) + se <- .safe(sqrt(diag(do.call("vcov", fun_args)))) } # vcov: character (with backward compatibility for `robust = TRUE`) diff --git a/R/methods_survey.R b/R/methods_survey.R index 5b0e4751c..04674bf8f 100644 --- a/R/methods_survey.R +++ b/R/methods_survey.R @@ -4,8 +4,6 @@ model_parameters.svyglm <- function(model, ci = 0.95, ci_method = "wald", - bootstrap = FALSE, - iterations = 1000, standardize = NULL, exponentiate = FALSE, p_adjust = NULL, @@ -16,25 +14,32 @@ model_parameters.svyglm <- function(model, ...) { if (insight::n_obs(model) > 1e4 && ci_method == "likelihood") { insight::format_alert( - "Likelihood confidence intervals may take longer time to compute. Use 'ci_method=\"wald\"' for faster computation of CIs." + "Likelihood confidence intervals may take longer time to compute. Use 'ci_method=\"wald\"' for faster computation of CIs." # nolint ) } - out <- .model_parameters_generic( - model = model, + # validation check, warn if unsupported argument is used. + dot_args <- .check_dots( + dots = list(...), + not_allowed = c("vcov", "vcov_args", "bootstrap"), + class(model)[1], + verbose = verbose + ) + + fun_args <- list( + model, ci = ci, ci_method = ci_method, - bootstrap = bootstrap, - iterations = iterations, - merge_by = "Parameter", standardize = standardize, exponentiate = exponentiate, p_adjust = p_adjust, keep_parameters = keep, drop_parameters = drop, summary = summary, - ... + verbose = verbose ) + fun_args <- c(fun_args, dot_args) + out <- do.call(".model_parameters_generic", fun_args) attr(out, "object_name") <- insight::safe_deparse_symbol(substitute(model)) out @@ -115,8 +120,8 @@ ci.svyolr <- ci.svyglm #' @export p_value.svyglm <- function(model, verbose = TRUE, ...) { statistic <- insight::get_statistic(model) - df <- insight::get_df(model, type = "residual") - p <- 2 * stats::pt(-abs(statistic$Statistic), df = df) + dof <- insight::get_df(model, type = "residual") + p <- 2 * stats::pt(-abs(statistic$Statistic), df = dof) .data_frame( Parameter = statistic$Parameter, p = as.vector(p) diff --git a/R/utils_model_parameters.R b/R/utils_model_parameters.R index a59b48d22..eef3a86cc 100644 --- a/R/utils_model_parameters.R +++ b/R/utils_model_parameters.R @@ -245,7 +245,7 @@ "Coefficient" ) } - } else if (!is.null(info) && !info$family == "unknown") { + } else if (!is.null(info) && info$family != "unknown") { if (isTRUE(exponentiate)) { if (info$is_exponential && identical(info$link_function, "log")) { coef_col <- "Prevalence Ratio" @@ -348,7 +348,7 @@ ) # add Group variable - if (!is.null(clean_params$Group) && any(nchar(clean_params$Group) > 0)) { + if (!is.null(clean_params$Group) && any(nzchar(clean_params$Group, keepNA = TRUE))) { params$Group <- .safe(gsub("(.*): (.*)", "\\2", clean_params$Group)) } @@ -414,10 +414,10 @@ .additional_arguments <- function(x, value, default) { - args <- attributes(x)$additional_arguments + add_args <- attributes(x)$additional_arguments - if (length(args) > 0 && value %in% names(args)) { - out <- args[[value]] + if (length(add_args) > 0 && value %in% names(add_args)) { + out <- add_args[[value]] } else { out <- attributes(x)[[value]] } diff --git a/tests/testthat/_snaps/windows/model_parameters.logistf.md b/tests/testthat/_snaps/windows/model_parameters.logistf.md new file mode 100644 index 000000000..d15d7ac16 --- /dev/null +++ b/tests/testthat/_snaps/windows/model_parameters.logistf.md @@ -0,0 +1,63 @@ +# model_parameters.logistf + + Code + params + Output + # Fixed Effects + + Parameter | Log-Odds | SE | 95% CI | Chi2(1) | p + ----------------------------------------------------------------- + (Intercept) | 0.12 | 0.48 | [-0.82, 1.07] | 0.06 | 0.802 + age | -1.11 | 0.41 | [-1.97, -0.31] | 7.51 | 0.006 + oc | -0.07 | 0.43 | [-0.94, 0.79] | 0.02 | 0.875 + vic | 2.27 | 0.54 | [ 1.27, 3.44] | 22.93 | < .001 + vicl | -2.11 | 0.53 | [-3.26, -1.12] | 19.10 | < .001 + vis | -0.79 | 0.41 | [-1.61, 0.02] | 3.70 | 0.054 + dia | 3.10 | 1.51 | [ 0.77, 8.03] | 7.90 | 0.005 + Message + + Uncertainty intervals (profile-likelihood) and p-values (two-tailed) + computed using a Wald z-distribution approximation. + +# model_parameters.flic + + Code + params + Output + # Fixed Effects + + Parameter | Log-Odds | SE | 95% CI | Chi2(1) | p + ----------------------------------------------------------------- + (Intercept) | 0.13 | 0.28 | [-0.82, 1.08] | 0.85 | 0.358 + age | -1.11 | 0.29 | [-1.97, -0.31] | 7.51 | 0.006 + oc | -0.07 | 0.24 | [-0.94, 0.79] | 0.02 | 0.875 + vic | 2.27 | 0.24 | [ 1.27, 3.44] | 22.93 | < .001 + vicl | -2.11 | 0.25 | [-3.26, -1.12] | 19.10 | < .001 + vis | -0.79 | 0.26 | [-1.61, 0.02] | 3.70 | 0.054 + dia | 3.10 | 0.41 | [ 0.77, 8.03] | 7.90 | 0.005 + Message + + Uncertainty intervals (profile-likelihood) and p-values (two-tailed) + computed using a Wald z-distribution approximation. + +# model_parameters.flac + + Code + params + Output + # Fixed Effects + + Parameter | Log-Odds | SE | 95% CI | Chi2(1) | p + ----------------------------------------------------------------- + (Intercept) | 0.12 | 0.48 | [-0.81, 1.07] | 0.07 | 0.797 + age | -1.10 | 0.42 | [-1.95, -0.31] | 7.55 | 0.006 + oc | -0.07 | 0.43 | [-0.93, 0.79] | 0.02 | 0.879 + vic | 2.28 | 0.54 | [ 1.29, 3.43] | 23.37 | < .001 + vicl | -2.11 | 0.53 | [-3.24, -1.13] | 19.45 | < .001 + vis | -0.79 | 0.41 | [-1.60, 0.01] | 3.74 | 0.053 + dia | 3.18 | 1.53 | [ 0.87, 7.99] | 8.54 | 0.003 + Message + + Uncertainty intervals (profile-likelihood) and p-values (two-tailed) + computed using a Wald z-distribution approximation. + diff --git a/tests/testthat/test-model_parameters.logistf.R b/tests/testthat/test-model_parameters.logistf.R new file mode 100644 index 000000000..f8d4664e8 --- /dev/null +++ b/tests/testthat/test-model_parameters.logistf.R @@ -0,0 +1,27 @@ +skip_on_cran() + +skip_if_not_installed("logistf") +skip_if_not_installed("withr") + +withr::with_options( + list(parameters_exponentiate = FALSE), + { + data(sex2, package = "logistf") + m1 <- logistf::logistf(case ~ age + oc + vic + vicl + vis + dia, data = sex2) + m2 <- logistf::flic(m1) + m3 <- logistf::flac(m1, data = sex2) + + test_that("model_parameters.logistf", { + params <- model_parameters(m1) + expect_snapshot(params, variant = "windows") + }) + test_that("model_parameters.flic", { + params <- model_parameters(m2) + expect_snapshot(params, variant = "windows") + }) + test_that("model_parameters.flac", { + params <- model_parameters(m3) + expect_snapshot(params, variant = "windows") + }) + } +) diff --git a/tests/testthat/test-survey.R b/tests/testthat/test-survey.R new file mode 100644 index 000000000..71df946cc --- /dev/null +++ b/tests/testthat/test-survey.R @@ -0,0 +1,37 @@ +skip_if_not_installed("withr") +skip_if_not_installed("survey") + +withr::with_environment( + new.env(), + test_that("model_parameters svytable", { + # svychisq is called in model_parameters + svychisq <<- survey::svychisq + + data(api, package = "survey") + dclus1 <<- survey::svydesign(id = ~dnum, weights = ~pw, data = apiclus1, fpc = ~fpc) + m <- survey::svytable(~ sch.wide + stype, dclus1) + mp <- model_parameters(m) + expect_named(mp, c("F", "df", "df_error", "p", "Method")) + expect_equal(mp$p, 0.02174746, tolerance = 1e-3) + }) +) + +withr::with_environment( + new.env(), + test_that("model_parameters, bootstrap svyglm", { + data(api, package = "survey") + dstrat <- survey::svydesign( + id = ~1, + strata = ~stype, + weights = ~pw, + data = apistrat, + fpc = ~fpc + ) + + model_svyglm <- suppressWarnings(survey::svyglm(sch.wide ~ ell + meals + mobility, + design = dstrat, + family = binomial(link = "logit") + )) + expect_message(parameters(model_svyglm, bootstrap = TRUE), regex = "arguments are not supported") + }) +) diff --git a/tests/testthat/test-svytable.R b/tests/testthat/test-svytable.R deleted file mode 100644 index 8e6792b94..000000000 --- a/tests/testthat/test-svytable.R +++ /dev/null @@ -1,12 +0,0 @@ -test_that("model_parameters", { - skip_if_not_installed("survey") - # svychisq is called in model_parameters - svychisq <<- survey::svychisq - - data(api, package = "survey") - dclus1 <<- survey::svydesign(id = ~dnum, weights = ~pw, data = apiclus1, fpc = ~fpc) - m <- survey::svytable(~ sch.wide + stype, dclus1) - mp <- model_parameters(m) - expect_equal(colnames(mp), c("F", "df", "df_error", "p", "Method")) - expect_equal(mp$p, 0.02174746, tolerance = 1e-3) -})