From 0dd407b59106f6c9f3333c75057a6a916ec2ae03 Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 26 Jan 2024 12:11:59 +0100 Subject: [PATCH 01/14] fix format issue --- DESCRIPTION | 2 +- NEWS.md | 3 ++ R/compare_parameters.R | 8 ++--- R/format.R | 10 +++++++ R/utils_format.R | 9 ++++-- tests/testthat/test-format_model_parameters.R | 29 +++++++++++++++++++ 6 files changed, 53 insertions(+), 8 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index def576fa6..341742774 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Type: Package Package: parameters Title: Processing of Model Parameters -Version: 0.21.3.8 +Version: 0.21.3.9 Authors@R: c(person(given = "Daniel", family = "Lüdecke", diff --git a/NEWS.md b/NEWS.md index 4231e793d..fdf73cf56 100644 --- a/NEWS.md +++ b/NEWS.md @@ -24,6 +24,9 @@ * `print(include_reference = TRUE)` for `model_parameters()` did not work when run inside a pipe-chain. +* Fixed issues with `format()` for objects returned by `compare_parameters()` + that included mixed models. + # parameters 0.21.3 ## Changes diff --git a/R/compare_parameters.R b/R/compare_parameters.R index 203d10915..70048b324 100644 --- a/R/compare_parameters.R +++ b/R/compare_parameters.R @@ -98,7 +98,7 @@ compare_parameters <- function(..., names(models) <- model_names } } else { - model_names <- match.call(expand.dots = FALSE)$`...` + model_names <- match.call(expand.dots = FALSE)[["..."]] if (length(names(model_names)) > 0) { model_names <- names(model_names) } else if (any(vapply(model_names, is.call, TRUE))) { @@ -275,14 +275,14 @@ compare_models <- compare_parameters } } else { match_pretty_names <- att$pretty_names[x$Parameter] - if (!anyNA(match_pretty_names)) { - x$Parameter <- att$pretty_names[x$Parameter] - } else { + if (anyNA(match_pretty_names)) { match_pretty_names <- match(names(att$pretty_names), x$Parameter) match_pretty_names <- match_pretty_names[!is.na(match_pretty_names)] if (length(match_pretty_names)) { x$Parameter[match_pretty_names] <- att$pretty_names[x$Parameter[match_pretty_names]] } + } else { + x$Parameter <- att$pretty_names[x$Parameter] } } } diff --git a/R/format.R b/R/format.R index 68bbab5d9..c160924c9 100644 --- a/R/format.R +++ b/R/format.R @@ -426,6 +426,13 @@ format.compare_parameters <- function(x, formatted_table <- split(out, f = split_by) formatted_table <- lapply(names(formatted_table), function(tab) { i <- formatted_table[[tab]] + # check if data frame is empty - this may happen if not all combinations + # of split_by factors are present in the data (e.g., zero-inflated mixed + # models, that have random effects for the count, but not for the zero- + # inflation component) + if (nrow(i) == 0L) { + return(NULL) + } # remove unique columns if (insight::n_unique(i$Component) == 1L) i$Component <- NULL if (insight::n_unique(i$Effects) == 1L) i$Effects <- NULL @@ -447,6 +454,9 @@ format.compare_parameters <- function(x, i }) + # remove empty tables + formatted_table <- insight::compact_list(formatted_table) + # for HTML, bind data frames if (identical(format, "html")) { # fix non-equal length of columns and bind data frames diff --git a/R/utils_format.R b/R/utils_format.R index 968e01e29..9b140cb04 100644 --- a/R/utils_format.R +++ b/R/utils_format.R @@ -328,9 +328,12 @@ } -.add_reference_level <- function(params) { - # check if we have a model object, else return parameter table - model <- .get_object(params) +.add_reference_level <- function(params, model = NULL) { + if (is.null(model)) { + # check if we have a model object, if not provided by user + model <- .get_object(params) + } + # no model object provided? Try to get data from model call if (is.null(model)) { # get data from model call model_data <- .safe(eval(attributes(params)$model_call$data)) diff --git a/tests/testthat/test-format_model_parameters.R b/tests/testthat/test-format_model_parameters.R index 1e7b1ebfc..6e007f864 100644 --- a/tests/testthat/test-format_model_parameters.R +++ b/tests/testthat/test-format_model_parameters.R @@ -173,3 +173,32 @@ withr::with_options( }) } ) + +skip_if_not_installed("lme4") +skip_if_not_installed("glmmTMB") + +test_that("format, compare_parameters, mixed models", { + data(mtcars) + data(Salamanders, package = "glmmTMB") + model1 <- lme4::lmer(mpg ~ wt + (1 | gear), data = mtcars) + model2 <- glmmTMB::glmmTMB( + count ~ spp + mined + (1 | site), + ziformula = ~mined, + family = poisson(), + data = Salamanders + ) + out <- compare_parameters(model1, model2, effects = "all", component = "all") + f <- format(out) + expect_length(f, 3) + f <- format(out, format = "html") + expect_identical( + f$Component, + c( + "Fixed Effects", "Fixed Effects", "Fixed Effects", "Fixed Effects", + "Fixed Effects", "Fixed Effects", "Fixed Effects", "Fixed Effects", + "Fixed Effects", "Fixed Effects (Zero-Inflation Component)", + "Fixed Effects (Zero-Inflation Component)", "Random Effects", + "Random Effects", "Random Effects" + ) + ) +}) From 96f8b1d8f5d42b8f09418e004044d9e848b896a2 Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 26 Jan 2024 15:51:25 +0100 Subject: [PATCH 02/14] draft print_table --- DESCRIPTION | 3 +- NAMESPACE | 1 + R/compare_parameters.R | 15 +++- R/format.R | 20 +----- R/print_table.R | 139 ++++++++++++++++++++++++++++++++++++++ R/utils_format.R | 24 +++++++ man/compare_parameters.Rd | 8 +++ man/parameters-package.Rd | 1 - 8 files changed, 190 insertions(+), 21 deletions(-) create mode 100644 R/print_table.R diff --git a/DESCRIPTION b/DESCRIPTION index 341742774..71a9d4387 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -197,6 +197,7 @@ Suggests: survival, testthat, tidyselect, + tinytable, TMB, truncreg, VGAM, @@ -206,7 +207,7 @@ VignetteBuilder: knitr Encoding: UTF-8 Language: en-US -RoxygenNote: 7.2.3 +RoxygenNote: 7.3.1 Roxygen: list(markdown = TRUE) Config/testthat/edition: 3 Config/testthat/parallel: true diff --git a/NAMESPACE b/NAMESPACE index fd981009e..c4c90febb 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -965,6 +965,7 @@ export(pool_parameters) export(principal_components) export(print_html) export(print_md) +export(print_table) export(random_parameters) export(reduce_data) export(reduce_parameters) diff --git a/R/compare_parameters.R b/R/compare_parameters.R index 70048b324..7257fee24 100644 --- a/R/compare_parameters.R +++ b/R/compare_parameters.R @@ -16,6 +16,11 @@ #' @param ci_method Method for computing degrees of freedom for p-values #' and confidence intervals (CI). See documentation for related model class #' in [model_parameters()]. +#' @param coefficient_names Character vector with strings that should be used +#' as column headers for the coefficient column. Must be of same length as +#' number of models in `...`, or length 1. If length 1, this name will be +#' used for all coefficient columns. If `NULL`, the name for the coefficient +#' column will detected automatically (as in `model_parameters()`). #' @inheritParams model_parameters.default #' @inheritParams model_parameters.cpglmm #' @inheritParams print.parameters_model @@ -75,6 +80,7 @@ compare_parameters <- function(..., select = NULL, column_names = NULL, pretty_names = TRUE, + coefficient_names = NULL, keep = NULL, drop = NULL, verbose = TRUE) { @@ -146,6 +152,11 @@ compare_parameters <- function(..., } } + # make sure we have enough coefficient names - else, repeat first value + if (!is.null(coefficient_names) && length(coefficient_names) < length(models)) { + coefficient_names <- rep(coefficient_names[1], length(models)) + } + # iterate all models and create list of model parameters m <- lapply(seq_along(models), function(i) { model <- models[[i]] @@ -181,8 +192,10 @@ compare_parameters <- function(..., # set specific names for coefficient column coef_name <- attributes(dat)$coefficient_name - if (!is.null(coef_name)) { + if (!is.null(coef_name) && is.null(coefficient_names)) { colnames(dat)[colnames(dat) == "Coefficient"] <- coef_name + } else if (!is.null(coefficient_names)) { + colnames(dat)[colnames(dat) == "Coefficient"] <- coefficient_names[i] } # set pretty parameter names diff --git a/R/format.R b/R/format.R index c160924c9..ea5dd4466 100644 --- a/R/format.R +++ b/R/format.R @@ -107,24 +107,8 @@ format.parameters_model <- function(x, # check if we have mixed models with random variance parameters # in such cases, we don't need the group-column, but we rather # merge it with the parameter column - if (isTRUE(random_variances) && !is.null(x$Group) && !is.null(x$Effects)) { - ran_pars <- which(x$Effects == "random") - stddevs <- startsWith(x$Parameter[ran_pars], "SD (") - x$Parameter[ran_pars[stddevs]] <- paste0( - gsub("(.*)\\)", "\\1", x$Parameter[ran_pars[stddevs]]), - ": ", - x$Group[ran_pars[stddevs]], - ")" - ) - corrs <- startsWith(x$Parameter[ran_pars], "Cor (") - x$Parameter[ran_pars[corrs]] <- paste0( - gsub("(.*)\\)", "\\1", x$Parameter[ran_pars[corrs]]), - ": ", - x$Group[ran_pars[corrs]], - ")" - ) - x$Parameter[x$Parameter == "SD (Observations: Residual)"] <- "SD (Residual)" - x$Group <- NULL + if (isTRUE(random_variances)) { + x <- .format_ranef_parameters(x) } # group parameters - this function find those parameters that should be diff --git a/R/print_table.R b/R/print_table.R new file mode 100644 index 000000000..be5980c0b --- /dev/null +++ b/R/print_table.R @@ -0,0 +1,139 @@ +#' @export +print_table <- function(x, digits = 2, p_digits = 3, ...) { + insight::check_if_installed(c("datawizard", "tinytable")) + + if (!inherits(x, "compare_parameters")) { + insight::format_error("`print_table` can only be used with `compare_parameters` objects.") + } + + # random parameters? + random_variances <- any(unlist(lapply(attributes(x)$all_attributes, function(i) { + i$ran_pars + }))) + + # remember attributes + ci_lvl <- attributes(x)$all_attributes[[1]]$ci + model_names <- attributes(x)$model_names + + # check if we have mixed models with random variance parameters. in such + # cases, we don't need the group-column, but we rather merge it with the + # parameter column + if (isTRUE(random_variances)) { + # if (any(c("brmsfit", "stanreg", "stanmvreg") %in% m_class)) { + # # rename random effect parameters names for stan models + # x <- .format_stan_parameters(x) + # } else { + # x <- .format_ranef_parameters(x) + # } + x <- .format_ranef_parameters(x) + x$Group <- NULL + } + + # check if we have models with extra components (e.g., zero-inflated models) + # if so, we need to create a group variable, so we can include subheaders in + # the table, and we want to re-arrange rows + if (!is.null(x$Component) || !is.null(x$Effects)) { + # create group variable, so we can include subheaders in table + x$groups <- paste0(x$Component, ".", x$Effects) + x <- datawizard::data_arrange(x, c("Effects", "Component")) + # remove further unused columns + x$Component <- NULL + x$Effects <- NULL + } + + # we now iterate all model columns, remove non-used columns per model, + # and create the formated CI columns etc. + for (i in model_names) { + x[paste0("SE.", i)] <- NULL + x[paste0("df_error.", i)] <- NULL + x[paste0("z.", i)] <- NULL + x[paste0("t.", i)] <- NULL + ci_pos <- which(colnames(x) == paste0("CI.", i)) + x[paste0("CI.", i)] <- NULL + + # format estimate columns + estimate_col <- min(which(endsWith(colnames(x), paste0(".", i)))) + x[[estimate_col]] <- insight::format_value( + x[[estimate_col]], + digits = digits, + zap_small = TRUE + ) + + # format CI columns + x$CI <- insight::format_ci( + x[[paste0("CI_low.", i)]], + x[[paste0("CI_high.", i)]], + digits = digits, + ci = NULL, + brackets = FALSE, + zap_small = TRUE + ) + colnames(x)[colnames(x) == "CI"] <- paste0(sprintf("%g", 100 * ci_lvl), "% CI.", i) + x[paste0("CI_low.", i)] <- NULL + x[paste0("CI_high.", i)] <- NULL + + # format p-values + x[[paste0("p.", i)]] <- insight::format_p( + x[[paste0("p.", i)]], + digits = p_digits, + name = NULL + ) + + # relocate CI columns to right position + x <- x[c(1:(ci_pos - 1), ncol(x), ci_pos:(ncol(x) - 1))] + } + + # used for subgroup headers, if available + row_header_pos <- row_header_labels <- NULL + + if (!is.null(x$groups)) { + # find start row of each subgroup + row_header_pos <- which(!duplicated(x$groups)) + group_headers <- as.vector(x$groups[row_header_pos]) + for (i in seq_along(group_headers)) { + gh <- .format_model_component_header( + x = NULL, + type = group_headers[i], + split_column = "", + is_zero_inflated = FALSE, + is_ordinal_model = FALSE, + is_multivariate = FALSE, + ran_pars = random_variances, + formatted_table = NULL + ) + group_headers[i] <- gh$name + } + # create named list, required for tinytables + row_header_labels <- as.list(stats::setNames(row_header_pos, group_headers)) + # since we have the group names in "row_header_labels" now , we can remove the column + x$groups <- NULL + # make sure that the row header positions are correct - each header + # must be shifted by the number of rows above + for (i in 2:length(row_header_pos)) { + row_header_pos[i] <- row_header_pos[i] + (i - 1) + } + } + + # find out position of column groups + col_groups <- lapply(model_names, function(i) { + which(endsWith(colnames(x), paste0(".", i))) + }) + names(col_groups) <- model_names + + # fix column names + for (i in model_names) { + colnames(x) <- gsub(paste0("\\.", i, "$"), "", colnames(x)) + } + + # base table + out <- tinytable::tt(x, caption = NULL, notes = NULL, ...) + # add subheaders, if any + if (!is.null(row_header_labels)) { + out <- tinytable::group_tt(out, i = row_header_labels, j = col_groups) + out <- tinytable::style_tt(out, i = row_header_pos, italic = TRUE) + } else { + out <- tinytable::group_tt(out, j = col_groups) + } + ## TODO: fix this and return "out" only, one https://github.com/vincentarelbundock/tinytable/issues/109 is resolved + print(out, output = "html") +} diff --git a/R/utils_format.R b/R/utils_format.R index 9b140cb04..91ad2024d 100644 --- a/R/utils_format.R +++ b/R/utils_format.R @@ -328,6 +328,30 @@ } +.format_ranef_parameters <- function(x) { + if (!is.null(x$Group) && !is.null(x$Effects)) { + ran_pars <- which(x$Effects == "random") + stddevs <- startsWith(x$Parameter[ran_pars], "SD (") + x$Parameter[ran_pars[stddevs]] <- paste0( + gsub("(.*)\\)", "\\1", x$Parameter[ran_pars[stddevs]]), + ": ", + x$Group[ran_pars[stddevs]], + ")" + ) + corrs <- startsWith(x$Parameter[ran_pars], "Cor (") + x$Parameter[ran_pars[corrs]] <- paste0( + gsub("(.*)\\)", "\\1", x$Parameter[ran_pars[corrs]]), + ": ", + x$Group[ran_pars[corrs]], + ")" + ) + x$Parameter[x$Parameter == "SD (Observations: Residual)"] <- "SD (Residual)" + x$Group <- NULL + } + x +} + + .add_reference_level <- function(params, model = NULL) { if (is.null(model)) { # check if we have a model object, if not provided by user diff --git a/man/compare_parameters.Rd b/man/compare_parameters.Rd index 894f830da..db1dbf328 100644 --- a/man/compare_parameters.Rd +++ b/man/compare_parameters.Rd @@ -17,6 +17,7 @@ compare_parameters( select = NULL, column_names = NULL, pretty_names = TRUE, + coefficient_names = NULL, keep = NULL, drop = NULL, verbose = TRUE @@ -34,6 +35,7 @@ compare_models( select = NULL, column_names = NULL, pretty_names = TRUE, + coefficient_names = NULL, keep = NULL, drop = NULL, verbose = TRUE @@ -149,6 +151,12 @@ labels will be used as parameters names. The latter only works for "labelled" data, i.e. if the data used to fit the model had \code{"label"} and \code{"labels"} attributes. See also section \emph{Global Options to Customize Messages when Printing}.} +\item{coefficient_names}{Character vector with strings that should be used +as column headers for the coefficient column. Must be of same length as +number of models in \code{...}, or length 1. If length 1, this name will be +used for all coefficient columns. If \code{NULL}, the name for the coefficient +column will detected automatically (as in \code{model_parameters()}).} + \item{keep}{Character containing a regular expression pattern that describes the parameters that should be included (for \code{keep}) or excluded (for \code{drop}) in the returned data frame. \code{keep} may also be a diff --git a/man/parameters-package.Rd b/man/parameters-package.Rd index 9140f6ffc..ab8407b4f 100644 --- a/man/parameters-package.Rd +++ b/man/parameters-package.Rd @@ -3,7 +3,6 @@ \docType{package} \name{parameters-package} \alias{parameters-package} -\alias{_PACKAGE} \title{parameters: Extracting, Computing and Exploring the Parameters of Statistical Models using R} \description{ \strong{parameters}' primary goal is to provide utilities for processing the From d63950c84a694ec81c3bc98ddab951c023f44202 Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 26 Jan 2024 22:29:04 +0100 Subject: [PATCH 03/14] workaround --- R/print_table.R | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/R/print_table.R b/R/print_table.R index be5980c0b..b2fd25afa 100644 --- a/R/print_table.R +++ b/R/print_table.R @@ -134,6 +134,10 @@ print_table <- function(x, digits = 2, p_digits = 3, ...) { } else { out <- tinytable::group_tt(out, j = col_groups) } - ## TODO: fix this and return "out" only, one https://github.com/vincentarelbundock/tinytable/issues/109 is resolved - print(out, output = "html") + # workaround, to make sure HTML is default output + m <- attr(out, "tinytable_meta") + m$output <- "html" + attr(out, "tinytable_meta") <- m + + out } From 7da1b83aaa6dd90ce35e860e3445e1adf28d2e92 Mon Sep 17 00:00:00 2001 From: Daniel Date: Sat, 27 Jan 2024 14:12:27 +0100 Subject: [PATCH 04/14] docs --- R/display.R | 4 +++- R/methods_glmmTMB.R | 26 +++++++++++------------- R/methods_lme4.R | 35 ++++++++++++++------------------- R/print_html.R | 4 ++-- R/print_table.R | 19 ++++++++++++++++++ man/display.parameters_model.Rd | 9 +++++++-- man/model_parameters.merMod.Rd | 35 +++++++++++++++------------------ 7 files changed, 74 insertions(+), 58 deletions(-) diff --git a/R/display.R b/R/display.R index 51f26d532..52a0aa9b7 100644 --- a/R/display.R +++ b/R/display.R @@ -2,7 +2,9 @@ #' @name display.parameters_model #' #' @description Prints tables (i.e. data frame) in different output formats. -#' `print_md()` is a alias for `display(format = "markdown")`. +#' `print_md()` is a alias for `display(format = "markdown")`, `print_html()` +#' is a alias for `display(format = "html")`. `print_table()` is for specific +#' use cases only, and currently only works for `compare_parameters()` objects. #' #' @param x An object returned by [`model_parameters()`][model_parameters]. #' @param object An object returned by [`model_parameters()`][model_parameters], diff --git a/R/methods_glmmTMB.R b/R/methods_glmmTMB.R index ccef7de94..291a4ca7a 100644 --- a/R/methods_glmmTMB.R +++ b/R/methods_glmmTMB.R @@ -320,22 +320,20 @@ standard_error.glmmTMB <- function(model, ) if (effects == "random") { - if (requireNamespace("TMB", quietly = TRUE) && requireNamespace("glmmTMB", quietly = TRUE)) { - s1 <- TMB::sdreport(model$obj, getJointPrecision = TRUE) - s2 <- sqrt(s1$diag.cov.random) - rand.ef <- glmmTMB::ranef(model)[[1]] - rand.se <- lapply(rand.ef, function(.x) { - cnt <- nrow(.x) * ncol(.x) - s3 <- s2[1:cnt] - s2 <- s2[-(1:cnt)] - d <- as.data.frame(matrix(sqrt(s3), ncol = ncol(.x), byrow = TRUE)) - colnames(d) <- colnames(.x) - d - }) - rand.se - } else { + if (!requireNamespace("TMB", quietly = TRUE) && !requireNamespace("glmmTMB", quietly = TRUE)) { return(NULL) } + s1 <- TMB::sdreport(model$obj, getJointPrecision = TRUE) + s2 <- sqrt(s1$diag.cov.random) + rand.ef <- glmmTMB::ranef(model)[[1]] + rand.se <- lapply(rand.ef, function(.x) { + cnt <- nrow(.x) * ncol(.x) + s3 <- s2[1:cnt] + s2 <- s2[-(1:cnt)] + d <- as.data.frame(matrix(sqrt(s3), ncol = ncol(.x), byrow = TRUE)) + colnames(d) <- colnames(.x) + d + }) } else { if (is.null(.check_component(model, component, verbose = verbose))) { return(NULL) diff --git a/R/methods_lme4.R b/R/methods_lme4.R index ee1bcd537..6eb50c384 100644 --- a/R/methods_lme4.R +++ b/R/methods_lme4.R @@ -82,29 +82,24 @@ #' use `effects = "fixed"`. There is also a [`plot()`-method](https://easystats.github.io/see/articles/parameters.html) #' implemented in the [**see**-package](https://easystats.github.io/see/). #' -#' @examples +#' @examplesIf require("lme4") && require("glmmTMB") #' library(parameters) -#' if (require("lme4")) { -#' data(mtcars) -#' model <- lmer(mpg ~ wt + (1 | gear), data = mtcars) -#' model_parameters(model) -#' } +#' data(mtcars) +#' model <- lme4::lmer(mpg ~ wt + (1 | gear), data = mtcars) +#' model_parameters(model) +#' #' \donttest{ -#' if (require("glmmTMB")) { -#' data(Salamanders) -#' model <- glmmTMB( -#' count ~ spp + mined + (1 | site), -#' ziformula = ~mined, -#' family = poisson(), -#' data = Salamanders -#' ) -#' model_parameters(model, effects = "all") -#' } +#' data(Salamanders, package = "glmmTMB") +#' model <- glmmTMB::glmmTMB( +#' count ~ spp + mined + (1 | site), +#' ziformula = ~mined, +#' family = poisson(), +#' data = Salamanders +#' ) +#' model_parameters(model, effects = "all") #' -#' if (require("lme4")) { -#' model <- lmer(mpg ~ wt + (1 | gear), data = mtcars) -#' model_parameters(model, bootstrap = TRUE, iterations = 50, verbose = FALSE) -#' } +#' model <- lme4::lmer(mpg ~ wt + (1 | gear), data = mtcars) +#' model_parameters(model, bootstrap = TRUE, iterations = 50, verbose = FALSE) #' } #' @return A data frame of indices related to the model's parameters. #' @export diff --git a/R/print_html.R b/R/print_html.R index daa902133..9b21d4180 100644 --- a/R/print_html.R +++ b/R/print_html.R @@ -233,7 +233,7 @@ print_html.compare_parameters <- function(x, if (!is.null(user_labels)) { new_labels <- c( colnames(out[["_data"]])[1], - rep(user_labels, length.out = ncol(out[["_data"]]) - 1) + rep_len(user_labels, ncol(out[["_data"]]) - 1) ) new_labels <- as.list(new_labels) } @@ -270,7 +270,7 @@ print_html.compare_parameters <- function(x, # check where last parameter row ends. For "compare_models()", the # first Parameter value after data rows is "". If this is not found, # simply use number of rows as last row - last_row <- which(out[["_data"]][[pcol_name]] == "")[1] + last_row <- which(!nzchar(as.character(out[["_data"]][[pcol_name]]), keepNA = TRUE))[1] if (is.na(last_row)) { last_row <- nrow(out[["_data"]]) } else { diff --git a/R/print_table.R b/R/print_table.R index b2fd25afa..40e32df00 100644 --- a/R/print_table.R +++ b/R/print_table.R @@ -1,3 +1,22 @@ +#' @examplesIf require("tinytable") && require("lme4") && require("glmmTMB") +#' \donttest{ +#' data(iris) +#' data(Salamanders, package = "glmmTMB") +#' m1 <- lm(Sepal.Length ~ Species * Petal.Length, data = iris) +#' m2 <- lme4::lmer( +#' Sepal.Length ~ Petal.Length + Petal.Width + (1 | Species), +#' data = iris +#' ) +#' m3 <- glmmTMB::glmmTMB( +#' count ~ spp + mined + (1 | site), +#' ziformula = ~mined, +#' family = poisson(), +#' data = Salamanders +#' ) +#' out <- compare_parameters(m1, m2, m3, effects = "all", components = "all") +#' print_table(out) +#' +#' @rdname display.parameters_model #' @export print_table <- function(x, digits = 2, p_digits = 3, ...) { insight::check_if_installed(c("datawizard", "tinytable")) diff --git a/man/display.parameters_model.Rd b/man/display.parameters_model.Rd index 28f44ad50..8c325f32d 100644 --- a/man/display.parameters_model.Rd +++ b/man/display.parameters_model.Rd @@ -1,6 +1,6 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/display.R, R/format.R, R/print_html.R, -% R/print_md.R +% R/print_md.R, R/print_table.R \name{display.parameters_model} \alias{display.parameters_model} \alias{display.parameters_sem} @@ -10,6 +10,7 @@ \alias{format.parameters_model} \alias{print_html.parameters_model} \alias{print_md.parameters_model} +\alias{print_table} \title{Print tables in different output formats} \usage{ \method{display}{parameters_model}( @@ -127,6 +128,8 @@ verbose = TRUE, ... ) + +print_table(x, digits = 2, p_digits = 3, ...) } \arguments{ \item{object}{An object returned by \code{\link[=model_parameters]{model_parameters()}}, @@ -281,7 +284,9 @@ class \code{gt_tbl}. } \description{ Prints tables (i.e. data frame) in different output formats. -\code{print_md()} is a alias for \code{display(format = "markdown")}. +\code{print_md()} is a alias for \code{display(format = "markdown")}, \code{print_html()} +is a alias for \code{display(format = "html")}. \code{print_table()} is for specific +use cases only, and currently only works for \code{compare_parameters()} objects. } \details{ \code{display()} is useful when the table-output from functions, diff --git a/man/model_parameters.merMod.Rd b/man/model_parameters.merMod.Rd index 2d339c69c..71c2874fb 100644 --- a/man/model_parameters.merMod.Rd +++ b/man/model_parameters.merMod.Rd @@ -548,29 +548,26 @@ which is converted into a p-value using \code{\link[bayestestR:pd_to_p]{bayestes } \examples{ +\dontshow{if (require("lme4") && require("glmmTMB")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} library(parameters) -if (require("lme4")) { - data(mtcars) - model <- lmer(mpg ~ wt + (1 | gear), data = mtcars) - model_parameters(model) -} +data(mtcars) +model <- lme4::lmer(mpg ~ wt + (1 | gear), data = mtcars) +model_parameters(model) + \donttest{ -if (require("glmmTMB")) { - data(Salamanders) - model <- glmmTMB( - count ~ spp + mined + (1 | site), - ziformula = ~mined, - family = poisson(), - data = Salamanders - ) - model_parameters(model, effects = "all") -} +data(Salamanders, package = "glmmTMB") +model <- glmmTMB::glmmTMB( + count ~ spp + mined + (1 | site), + ziformula = ~mined, + family = poisson(), + data = Salamanders +) +model_parameters(model, effects = "all") -if (require("lme4")) { - model <- lmer(mpg ~ wt + (1 | gear), data = mtcars) - model_parameters(model, bootstrap = TRUE, iterations = 50, verbose = FALSE) -} +model <- lme4::lmer(mpg ~ wt + (1 | gear), data = mtcars) +model_parameters(model, bootstrap = TRUE, iterations = 50, verbose = FALSE) } +\dontshow{\}) # examplesIf} } \seealso{ \code{\link[insight:standardize_names]{insight::standardize_names()}} to From 9c2e6a75d37443f98af43f85da1cd0dd4008aca5 Mon Sep 17 00:00:00 2001 From: Daniel Date: Sat, 27 Jan 2024 14:24:19 +0100 Subject: [PATCH 05/14] lintr --- R/format.R | 26 ++++++++++++++++---------- R/utils_format.R | 26 +++++++++++++------------- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/R/format.R b/R/format.R index ea5dd4466..c12e20a86 100644 --- a/R/format.R +++ b/R/format.R @@ -295,7 +295,7 @@ format.compare_parameters <- function(x, ran_group_rows <- NULL } else { ran_groups <- unique(insight::compact_character(x$Group)) - ran_group_rows <- which(nchar(x$Group) > 0) + ran_group_rows <- which(nzchar(x$Group, keepNA = TRUE)) } for (i in models) { @@ -325,9 +325,12 @@ format.compare_parameters <- function(x, # find SD random parameters stddevs <- startsWith(out$Parameter[ran_pars_rows], "SD (") # check if we already fixed that name in a previous loop - fixed_name <- unlist(lapply(ran_groups, function(g) { - which(grepl(g, out$Parameter[ran_pars_rows[stddevs]], fixed = TRUE)) - })) + fixed_name <- unlist(lapply( + ran_groups, + grep, + x = out$Parameter[ran_pars_rows[stddevs]], + fixed = TRUE + )) if (length(fixed_name)) { stddevs[fixed_name] <- FALSE } @@ -343,9 +346,12 @@ format.compare_parameters <- function(x, # same for correlations corrs <- startsWith(out$Parameter[ran_pars_rows], "Cor (") # check if we already fixed that name in a previous loop - fixed_name <- unlist(lapply(ran_groups, function(g) { - which(grepl(g, out$Parameter[ran_pars_rows[corrs]], fixed = TRUE)) - })) + fixed_name <- unlist(lapply( + ran_groups, + grep, + x = out$Parameter[ran_pars_rows[corrs]], + fixed = TRUE + )) if (length(fixed_name)) { corrs[fixed_name] <- FALSE } @@ -539,7 +545,7 @@ format.parameters_sem <- function(x, footer <- NULL type <- tolower(format) - sigma <- attributes(x)$sigma + sigma_value <- attributes(x)$sigma r2 <- attributes(x)$r2 residual_df <- attributes(x)$residual_df p_adjust <- attributes(x)$p_adjust @@ -559,7 +565,7 @@ format.parameters_sem <- function(x, # footer: residual standard deviation if (isTRUE(show_sigma)) { - footer <- .add_footer_sigma(footer, digits, sigma, residual_df, type) + footer <- .add_footer_sigma(footer, digits, sigma_value, residual_df, type) } # footer: r-squared @@ -870,7 +876,7 @@ format.parameters_sem <- function(x, string_approx <- "" } - if (!is.null(test_statistic) && !ci_method == "normal" && !isTRUE(bootstrap)) { + if (!is.null(test_statistic) && ci_method != "normal" && !isTRUE(bootstrap)) { string_statistic <- switch(tolower(test_statistic), `t-statistic` = "t", `chi-squared statistic` = , diff --git a/R/utils_format.R b/R/utils_format.R index 91ad2024d..c06107afc 100644 --- a/R/utils_format.R +++ b/R/utils_format.R @@ -587,26 +587,26 @@ if (grepl("^conditional\\.(r|R)andom_variances", component_name)) { component_name <- insight::trim_ws(gsub("^conditional\\.(r|R)andom_variances(\\.)*", "", component_name)) - if (nchar(component_name) == 0) { - component_name <- "Random Effects Variances" - } else { + if (nzchar(component_name, keepNA = TRUE)) { component_name <- paste0("Random Effects Variances: ", component_name) + } else { + component_name <- "Random Effects Variances" } } if (grepl("^conditional\\.(r|R)andom", component_name)) { component_name <- insight::trim_ws(gsub("^conditional\\.(r|R)andom(\\.)*", "", component_name)) - if (nchar(component_name) == 0) { - component_name <- ifelse(ran_pars, "Random Effects Variances", "Random Effects (Count Model)") - } else { + if (nzchar(component_name, keepNA = TRUE)) { component_name <- paste0("Random Effects (Count Model): ", component_name) + } else { + component_name <- ifelse(ran_pars, "Random Effects Variances", "Random Effects (Count Model)") } } if (grepl("^zero_inflated\\.(r|R)andom", component_name)) { component_name <- insight::trim_ws(gsub("^zero_inflated\\.(r|R)andom(\\.)*", "", component_name)) - if (nchar(component_name) == 0) { - component_name <- "Random Effects (Zero-Inflation Component)" - } else { + if (nzchar(component_name, keepNA = TRUE)) { component_name <- paste0("Random Effects (Zero-Inflation Component): ", component_name) + } else { + component_name <- "Random Effects (Zero-Inflation Component)" } } if (startsWith(component_name, "random.")) { @@ -858,7 +858,7 @@ if ("Subgroup" %in% names(x) && insight::n_unique(x$Subgroup) > 1) { split_by <- c(split_by, "Subgroup") } - split_by <- split_by[nchar(split_by) > 0] + split_by <- split_by[nzchar(split_by, keepNA = TRUE)] split_by } @@ -931,7 +931,7 @@ # fix column output if (inherits(attributes(x)$model, c("lavaan", "blavaan")) && "Label" %in% colnames(x)) { - x$From <- ifelse(x$Label == "" | x$Label == x$To, x$From, paste0(x$From, " (", x$Label, ")")) + x$From <- ifelse(!nzchar(as.character(x$Label), keepNA = TRUE) | x$Label == x$To, x$From, paste0(x$From, " (", x$Label, ")")) x$Label <- NULL } @@ -1024,8 +1024,8 @@ # Don't print if empty col tables[[type]][vapply(colnames(tables[[type]]), function(x) { - col <- tables[[type]][[x]] - (all(col == "") | all(is.na(col))) && !grepl("_CI_(high|low)$", x) + column <- tables[[type]][[x]] + (!any(nzchar(as.character(column), keepNA = TRUE)) | all(is.na(column))) && !grepl("_CI_(high|low)$", x) }, logical(1))] <- NULL attr(tables[[type]], "digits") <- digits From 6010e30f77da7dbc7a168f8bb315e6278e20fa5f Mon Sep 17 00:00:00 2001 From: Daniel Date: Sat, 27 Jan 2024 15:29:45 +0100 Subject: [PATCH 06/14] lintr --- R/extract_random_variances.R | 18 ++++++++--------- R/methods_mmrm.R | 38 +++++++++++++++++------------------- 2 files changed, 26 insertions(+), 30 deletions(-) diff --git a/R/extract_random_variances.R b/R/extract_random_variances.R index 83c3e079f..df9eef30f 100644 --- a/R/extract_random_variances.R +++ b/R/extract_random_variances.R @@ -159,9 +159,9 @@ } # rename sigma - sigma <- out$grp == "Residual" - if (any(sigma)) { - out$Parameter[sigma] <- "SD (Observations)" + sigma_res <- out$grp == "Residual" + if (any(sigma_res)) { + out$Parameter[sigma_res] <- "SD (Observations)" } # rename columns @@ -313,8 +313,8 @@ as.data.frame.VarCorr.lme <- function(x, row.names = NULL, optional = FALSE, ... if (is.null(ci_random)) { # check sample size, don't compute by default when larger than 1000 - nobs <- insight::n_obs(model) - if (nobs >= 1000) { + n_obs <- insight::n_obs(model) + if (n_obs >= 1000) { return(out) } @@ -323,7 +323,7 @@ as.data.frame.VarCorr.lme <- function(x, row.names = NULL, optional = FALSE, ... rs <- insight::find_random_slopes(model) # quit if if random slopes and larger sample size or more than 1 grouping factor - if (!is.null(rs) && (nobs >= 500 || length(re) > 1)) { + if (!is.null(rs) && (n_obs >= 500 || length(re) > 1)) { return(out) } @@ -382,10 +382,8 @@ as.data.frame.VarCorr.lme <- function(x, row.names = NULL, optional = FALSE, ... merDeriv_loaded <- isNamespaceLoaded("merDeriv") # detach on exit on.exit( - { - if (!merDeriv_loaded) { - .unregister_vcov() - } + if (!merDeriv_loaded) { + .unregister_vcov() }, add = TRUE, after = FALSE diff --git a/R/methods_mmrm.R b/R/methods_mmrm.R index af3b35469..b97598df5 100644 --- a/R/methods_mmrm.R +++ b/R/methods_mmrm.R @@ -21,26 +21,24 @@ model_parameters.mmrm <- function(model, # extract model parameters table, as data frame out <- tryCatch( - { - .model_parameters_generic( - model = model, - ci = ci, - ci_method = ci_method, - bootstrap = bootstrap, - iterations = iterations, - merge_by = "Parameter", - standardize = standardize, - exponentiate = exponentiate, - p_adjust = p_adjust, - summary = summary, - keep_parameters = keep, - drop_parameters = drop, - vcov = NULL, - vcov_args = NULL, - verbose = verbose, - ... - ) - }, + .model_parameters_generic( + model = model, + ci = ci, + ci_method = ci_method, + bootstrap = bootstrap, + iterations = iterations, + merge_by = "Parameter", + standardize = standardize, + exponentiate = exponentiate, + p_adjust = p_adjust, + summary = summary, + keep_parameters = keep, + drop_parameters = drop, + vcov = NULL, + vcov_args = NULL, + verbose = verbose, + ... + ), error = function(e) { fail <- NA attr(fail, "error") <- gsub(" ", " ", gsub("\\n", "", e$message), fixed = TRUE) From cb27a8981c675aa84550e8d8fb485f9a25b88a7f Mon Sep 17 00:00:00 2001 From: Daniel Date: Sat, 27 Jan 2024 15:51:48 +0100 Subject: [PATCH 07/14] lintr --- R/1_model_parameters.R | 38 ++++++++++++------------ R/5_simulate_model.R | 6 ++-- R/bootstrap_model.R | 16 +++++----- R/bootstrap_parameters.R | 4 +-- R/ci_generic.R | 8 ++--- R/cluster_analysis.R | 8 ++--- R/cluster_meta.R | 20 ++++++------- R/compare_parameters.R | 2 +- R/dof.R | 2 +- R/extract_parameters.R | 36 +++++++++++------------ R/methods_mlm.R | 21 ++++++------- R/methods_rstan.R | 2 +- R/n_factors.R | 46 ++++++++++++++--------------- R/print_table.R | 2 +- R/reduce_parameters.R | 24 +++++++-------- R/simulate_parameters.R | 4 +-- R/standardize_parameters.R | 6 ++-- R/utils.R | 2 +- R/utils_model_parameters.R | 34 ++++++++++----------- R/utils_pca_efa.R | 52 +++++++++++++++------------------ man/display.parameters_model.Rd | 19 ++++++++++++ 21 files changed, 174 insertions(+), 178 deletions(-) diff --git a/R/1_model_parameters.R b/R/1_model_parameters.R index aa8106750..991a3704d 100644 --- a/R/1_model_parameters.R +++ b/R/1_model_parameters.R @@ -489,26 +489,24 @@ model_parameters.default <- function(model, # extract model parameters table, as data frame out <- tryCatch( - { - .model_parameters_generic( - model = model, - ci = ci, - ci_method = ci_method, - bootstrap = bootstrap, - iterations = iterations, - merge_by = "Parameter", - standardize = standardize, - exponentiate = exponentiate, - p_adjust = p_adjust, - summary = summary, - keep_parameters = keep, - drop_parameters = drop, - vcov = vcov, - vcov_args = vcov_args, - verbose = verbose, - ... - ) - }, + .model_parameters_generic( + model = model, + ci = ci, + ci_method = ci_method, + bootstrap = bootstrap, + iterations = iterations, + merge_by = "Parameter", + standardize = standardize, + exponentiate = exponentiate, + p_adjust = p_adjust, + summary = summary, + keep_parameters = keep, + drop_parameters = drop, + vcov = vcov, + vcov_args = vcov_args, + verbose = verbose, + ... + ), error = function(e) { fail <- NA attr(fail, "error") <- gsub(" ", " ", gsub("\\n", "", e$message), fixed = TRUE) diff --git a/R/5_simulate_model.R b/R/5_simulate_model.R index 1805cc1d2..41bacfb6e 100644 --- a/R/5_simulate_model.R +++ b/R/5_simulate_model.R @@ -233,11 +233,11 @@ simulate_model.bracl <- simulate_model.default if (is.null(iterations)) iterations <- 1000 params <- insight::get_parameters(model, effects = effects, component = component, verbose = FALSE) - beta <- stats::setNames(params$Estimate, params$Parameter) # Transform to named vector + beta_mu <- stats::setNames(params$Estimate, params$Parameter) # Transform to named vector # "..." allow specification of vcov-args (#784) varcov <- insight::get_varcov(model, component = component, effects = effects, ...) - as.data.frame(.mvrnorm(n = iterations, mu = beta, Sigma = varcov)) + as.data.frame(.mvrnorm(n = iterations, mu = beta_mu, Sigma = varcov)) ## Alternative approach, similar to arm::sim() @@ -248,7 +248,7 @@ simulate_model.bracl <- simulate_model.default # b <- array(NA, c(100, k)) # for (i in 1:iterations) { # s[i] <- stats::sigma(model) * sqrt((n - k) / rchisq(1, n - k)) - # b[i,] <- .mvrnorm(n = 1, mu = beta, Sigma = beta.cov * s[i] ^ 2) + # b[i,] <- .mvrnorm(n = 1, mu = beta_mu, Sigma = beta.cov * s[i] ^ 2) # } } diff --git a/R/bootstrap_model.R b/R/bootstrap_model.R index db927629f..949bc415a 100644 --- a/R/bootstrap_model.R +++ b/R/bootstrap_model.R @@ -78,7 +78,7 @@ bootstrap_model.default <- function(model, type <- match.arg(type, choices = c("ordinary", "parametric", "balanced", "permutation", "antithetic")) parallel <- match.arg(parallel) - model_data <- data <- insight::get_data(model, verbose = FALSE) + model_data <- data <- insight::get_data(model, verbose = FALSE) # nolint model_response <- insight::find_response(model) boot_function <- function(model, data, indices) { @@ -86,12 +86,10 @@ bootstrap_model.default <- function(model, if (inherits(model, "biglm")) { fit <- suppressMessages(stats::update(model, moredata = d)) + } else if (verbose) { + fit <- stats::update(model, data = d) } else { - if (verbose) { - fit <- stats::update(model, data = d) - } else { - fit <- suppressMessages(stats::update(model, data = d)) - } + fit <- suppressMessages(stats::update(model, data = d)) } params <- insight::get_parameters(fit, verbose = FALSE) @@ -103,7 +101,7 @@ bootstrap_model.default <- function(model, params <- stats::setNames(params$Estimate, params$Parameter) # Transform to named vector } - return(params) + params } if (type == "parametric") { @@ -111,7 +109,7 @@ bootstrap_model.default <- function(model, out <- model_data resp <- stats::simulate(x, nsim = 1) out[[model_response]] <- resp - return(out) + out } results <- boot::boot( data = data, @@ -233,7 +231,7 @@ bootstrap_model.nestedLogit <- function(model, type <- match.arg(type, choices = c("ordinary", "balanced", "permutation", "antithetic")) parallel <- match.arg(parallel) - model_data <- data <- insight::get_data(model, verbose = FALSE) + model_data <- data <- insight::get_data(model, verbose = FALSE) # nolint model_response <- insight::find_response(model) boot_function <- function(model, data, indices) { diff --git a/R/bootstrap_parameters.R b/R/bootstrap_parameters.R index cf21ecf1a..474731c09 100644 --- a/R/bootstrap_parameters.R +++ b/R/bootstrap_parameters.R @@ -60,8 +60,8 @@ bootstrap_parameters.default <- function(model, ci_method = "quantile", test = "p-value", ...) { - data <- bootstrap_model(model, iterations = iterations, ...) - bootstrap_parameters(data, centrality = centrality, ci = ci, ci_method = ci_method, test = test, ...) + boot_data <- bootstrap_model(model, iterations = iterations, ...) + bootstrap_parameters(boot_data, centrality = centrality, ci = ci, ci_method = ci_method, test = test, ...) } diff --git a/R/ci_generic.R b/R/ci_generic.R index 60776f5be..d026adc13 100644 --- a/R/ci_generic.R +++ b/R/ci_generic.R @@ -26,7 +26,7 @@ effects <- match.arg(effects) component <- match.arg(component) - if (method == "ml1") { + if (method == "ml1") { # nolint return(ci_ml1(model, ci = ci)) } else if (method == "betwithin") { return(ci_betwithin(model, ci = ci)) @@ -110,9 +110,9 @@ ) } else { stderror <- switch(method, - "kenward" = se_kenward(model), - "kr" = se_kenward(model), - "satterthwaite" = se_satterthwaite(model), + kenward = se_kenward(model), + kr = se_kenward(model), + satterthwaite = se_satterthwaite(model), standard_error(model, component = component) ) } diff --git a/R/cluster_analysis.R b/R/cluster_analysis.R index 9bcf341ec..374f070be 100644 --- a/R/cluster_analysis.R +++ b/R/cluster_analysis.R @@ -446,7 +446,7 @@ summary.cluster_analysis <- function(object, ...) { #' @export visualisation_recipe.cluster_analysis_summary <- function(x, ...) { - data <- datawizard::data_to_long( + data_long <- datawizard::data_to_long( x, select = names(x)[-1], # skip 'Cluster' column names_to = "Group", @@ -459,13 +459,13 @@ visualisation_recipe.cluster_analysis_summary <- function(x, ...) { layers[["l1"]] <- list( geom = "bar", - data = data, + data = data_long, aes = list(x = "Cluster", y = "Center", fill = "Group"), position = "dodge" ) layers[["l2"]] <- list( geom = "hline", - data = data, + data = data_long, aes = list(yintercept = 0), linetype = "dotted" ) @@ -479,7 +479,7 @@ visualisation_recipe.cluster_analysis_summary <- function(x, ...) { # Out class(layers) <- c("visualisation_recipe", "see_visualisation_recipe", class(layers)) - attr(layers, "data") <- data + attr(layers, "data") <- data_long layers } diff --git a/R/cluster_meta.R b/R/cluster_meta.R index dfe737ec9..3d8335e0a 100644 --- a/R/cluster_meta.R +++ b/R/cluster_meta.R @@ -83,12 +83,12 @@ cluster_meta <- function(list_of_clusters, rownames = NULL, ...) { } # Convert to dataframe - data <- as.data.frame(x) - if (!is.null(names(solution))) row.names(data) <- names(solution) - if (!is.null(rownames)) row.names(data) <- rownames + cluster_data <- as.data.frame(x) + if (!is.null(names(solution))) row.names(cluster_data) <- names(solution) + if (!is.null(rownames)) row.names(cluster_data) <- rownames # Get probability matrix - m <- .cluster_meta_matrix(data) + m <- .cluster_meta_matrix(cluster_data) class(m) <- c("cluster_meta", class(m)) m } @@ -102,12 +102,10 @@ cluster_meta <- function(list_of_clusters, rownames = NULL, ...) { .get_prob <- function(x) { if (anyNA(x)) { NA + } else if (length(unique(x[!is.na(x)])) == 1) { + 0 } else { - if (length(unique(x[!is.na(x)])) == 1) { - 0 - } else { - 1 - } + 1 } } @@ -120,8 +118,8 @@ cluster_meta <- function(list_of_clusters, rownames = NULL, ...) { m[row, col] <- 0 next } - subset <- data[row.names(data) %in% c(row, col), ] - rez <- sapply(subset[2:ncol(subset)], .get_prob) + subset_rows <- data[row.names(data) %in% c(row, col), ] + rez <- sapply(subset_rows[2:ncol(subset_rows)], .get_prob) m[row, col] <- sum(rez, na.rm = TRUE) / length(stats::na.omit(rez)) } } diff --git a/R/compare_parameters.R b/R/compare_parameters.R index 7257fee24..cf6285cb7 100644 --- a/R/compare_parameters.R +++ b/R/compare_parameters.R @@ -246,7 +246,7 @@ compare_parameters <- function(..., all_models[model_cols] <- NULL # remove empty group-column - if (all(nchar(all_models$Group) == 0)) { + if (!any(nzchar(as.character(all_models$Group), keepNA = TRUE))) { all_models$Group <- NULL } diff --git a/R/dof.R b/R/dof.R index a1c5e8d8f..502714d34 100644 --- a/R/dof.R +++ b/R/dof.R @@ -118,7 +118,7 @@ degrees_of_freedom.default <- function(model, method = "analytical", ...) { } } - if (method == "any") { + if (method == "any") { # nolint dof <- .degrees_of_freedom_residual(model, verbose = FALSE) if (is.null(dof) || all(is.infinite(dof)) || anyNA(dof)) { dof <- .degrees_of_freedom_analytical(model, kenward = FALSE) diff --git a/R/extract_parameters.R b/R/extract_parameters.R index 997e75938..dcccdf5c9 100644 --- a/R/extract_parameters.R +++ b/R/extract_parameters.R @@ -527,26 +527,24 @@ ) 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" + } else if (ci_method %in% special_ci_methods) { + # special handling for KR-p, which we already have computed from dof + # parameters <- merge(parameters, .p_value_dof_kr(model, params = parameters, dof = df_error), by = "Parameter") + parameters <- merge( + parameters, + .p_value_dof(model, dof = df_error$df_error, method = ci_method, se = df_error$SE), + by = "Parameter", + sort = FALSE + ) } else { - if ("Pr(>|z|)" %in% names(parameters)) { - names(parameters)[grepl("Pr(>|z|)", names(parameters), fixed = TRUE)] <- "p" - } else if (ci_method %in% special_ci_methods) { - # special handling for KR-p, which we already have computed from dof - # parameters <- merge(parameters, .p_value_dof_kr(model, params = parameters, dof = df_error), by = "Parameter") - parameters <- merge( - parameters, - .p_value_dof(model, dof = df_error$df_error, method = ci_method, se = df_error$SE), - by = "Parameter", - sort = FALSE - ) - } else { - parameters <- merge( - parameters, - p_value(model, dof = dof, effects = "fixed"), - by = "Parameter", - sort = FALSE - ) - } + parameters <- merge( + parameters, + p_value(model, dof = dof, effects = "fixed"), + by = "Parameter", + sort = FALSE + ) } diff --git a/R/methods_mlm.R b/R/methods_mlm.R index f37328d16..5f1c1f2a7 100644 --- a/R/methods_mlm.R +++ b/R/methods_mlm.R @@ -80,9 +80,8 @@ standard_error.mlm <- function(model, se$Parameter <- est$Parameter se$Response <- est$Response return(se) - - # manually } else { + # manually if (!is.null(vcov)) { insight::format_warning( "Unable to extract the variance-covariance matrix requested in `vcov`." @@ -170,14 +169,12 @@ ci.mlm <- function(x, resp <- insight::get_parameters(x)$Response if (!"Response" %in% colnames(out) && nrow(out) == length(resp)) { out[["Response"]] <- resp - } else { - if (!isTRUE(all(out$Response == resp))) { - insight::format_error( - "Unable to assign labels to the model's parameters.", - "Please report this problem to the {.pkg parameters} issue tracker:", - "{.url https://github.com/easystats/parameters/issues}" - ) - } + } else if (!isTRUE(all(out$Response == resp))) { + insight::format_error( + "Unable to assign labels to the model's parameters.", + "Please report this problem to the {.pkg parameters} issue tracker:", + "{.url https://github.com/easystats/parameters/issues}" + ) } } out @@ -206,10 +203,10 @@ simulate_parameters.mlm <- 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_rstan.R b/R/methods_rstan.R index f4600faa4..95879286f 100644 --- a/R/methods_rstan.R +++ b/R/methods_rstan.R @@ -39,7 +39,7 @@ model_parameters.stanfit <- function(model, if (effects != "fixed") { random_effect_levels <- which( - params$Effects %in% "random" & !startsWith(params$Parameter, "Sigma[") + params$Effects == "random" & !startsWith(params$Parameter, "Sigma[") ) if (length(random_effect_levels) && isFALSE(group_level)) { params <- params[-random_effect_levels, ] diff --git a/R/n_factors.R b/R/n_factors.R index 9b6c335af..27b53c8ba 100644 --- a/R/n_factors.R +++ b/R/n_factors.R @@ -121,16 +121,14 @@ n_factors <- function(x, # Get number of observations if (is.data.frame(x)) { - nobs <- nrow(x) - } else { - if (is.numeric(x) && !is.null(cor)) { - nobs <- x - package <- package[!package %in% c("pcdimension", "PCDimension")] - } else if (is.matrix(x) || inherits(x, "easycormatrix")) { - insight::format_error( - "Please input the correlation matrix via the `cor` argument and the number of rows / observations via the first argument." # nolint - ) - } + n_obs <- nrow(x) + } else if (is.numeric(x) && !is.null(cor)) { + n_obs <- x + package <- package[!package %in% c("pcdimension", "PCDimension")] + } else if (is.matrix(x) || inherits(x, "easycormatrix")) { + insight::format_error( + "Please input the correlation matrix via the `cor` argument and the number of rows / observations via the first argument." # nolint + ) } # Get only numeric @@ -175,14 +173,14 @@ n_factors <- function(x, if (safe) { out <- rbind( out, - tryCatch(.n_factors_bartlett(eigen_values, model, nobs), + tryCatch(.n_factors_bartlett(eigen_values, model, n_obs), warning = function(w) data.frame(), error = function(e) data.frame() ) ) out <- rbind( out, - tryCatch(.n_factors_bentler(eigen_values, model, nobs), + tryCatch(.n_factors_bentler(eigen_values, model, n_obs), warning = function(w) data.frame(), error = function(e) data.frame() ) @@ -218,11 +216,11 @@ n_factors <- function(x, } else { out <- rbind( out, - .n_factors_bartlett(eigen_values, model, nobs) + .n_factors_bartlett(eigen_values, model, n_obs) ) out <- rbind( out, - .n_factors_bentler(eigen_values, model, nobs) + .n_factors_bentler(eigen_values, model, n_obs) ) out <- rbind( out, @@ -250,7 +248,7 @@ n_factors <- function(x, if (safe) { out <- rbind( out, - tryCatch(.n_factors_ega(x, cor, nobs, eigen_values, type), + tryCatch(.n_factors_ega(x, cor, n_obs, eigen_values, type), # warning = function(w) data.frame(), error = function(e) data.frame() ) @@ -258,7 +256,7 @@ n_factors <- function(x, } else { out <- rbind( out, - .n_factors_ega(x, cor, nobs, eigen_values, type) + .n_factors_ega(x, cor, n_obs, eigen_values, type) ) } } @@ -271,7 +269,7 @@ n_factors <- function(x, if (safe) { out <- rbind( out, - tryCatch(.n_factors_vss(x, cor, nobs, type, rotation, algorithm), + tryCatch(.n_factors_vss(x, cor, n_obs, type, rotation, algorithm), # warning = function(w) data.frame(), error = function(e) data.frame() ) @@ -279,7 +277,7 @@ n_factors <- function(x, } else { out <- rbind( out, - .n_factors_vss(x, cor, nobs, type, rotation, algorithm) + .n_factors_vss(x, cor, n_obs, type, rotation, algorithm) ) } } @@ -291,7 +289,7 @@ n_factors <- function(x, if (safe) { out <- rbind( out, - tryCatch(.n_factors_fit(x, cor, nobs, type, rotation, algorithm), + tryCatch(.n_factors_fit(x, cor, n_obs, type, rotation, algorithm), warning = function(w) data.frame(), error = function(e) data.frame() ) @@ -299,7 +297,7 @@ n_factors <- function(x, } else { out <- rbind( out, - .n_factors_fit(x, cor, nobs, type, rotation, algorithm) + .n_factors_fit(x, cor, n_obs, type, rotation, algorithm) ) } } @@ -403,7 +401,7 @@ print.n_factors <- function(x, ...) { # Text - text <- paste0( + msg_text <- paste0( "The choice of ", as.character(best_n), ifelse(type == "factor", " dimensions ", " clusters "), @@ -419,7 +417,7 @@ print.n_factors <- function(x, ...) { ) insight::print_color("# Method Agreement Procedure:\n\n", "blue") - cat(text) + cat(msg_text) invisible(x) } @@ -760,10 +758,10 @@ print.n_clusters <- print.n_factors CRMS <- rez[!is.na(rez$CRMS) & rez$CRMS <= target, "n"][1] } # BIC (this is a penalized method so we can just take the one that minimizes it) - BIC <- ifelse(all(is.na(rez$BIC)), NA, rez[!is.na(rez$BIC) & rez$BIC == min(rez$BIC, na.rm = TRUE), "n"]) + BayIC <- ifelse(all(is.na(rez$BIC)), NA, rez[!is.na(rez$BIC) & rez$BIC == min(rez$BIC, na.rm = TRUE), "n"]) .data_frame( - n_Factors = c(fit_off, TLI, RMSEA, RMSR, CRMS, BIC), + n_Factors = c(fit_off, TLI, RMSEA, RMSR, CRMS, BayIC), Method = c("Fit_off", "TLI", "RMSEA", "RMSR", "CRMS", "BIC"), Family = c("Fit", "Fit", "Fit", "Fit", "Fit", "Fit") ) diff --git a/R/print_table.R b/R/print_table.R index 40e32df00..9ee2b3846 100644 --- a/R/print_table.R +++ b/R/print_table.R @@ -15,7 +15,7 @@ #' ) #' out <- compare_parameters(m1, m2, m3, effects = "all", components = "all") #' print_table(out) -#' +#' } #' @rdname display.parameters_model #' @export print_table <- function(x, digits = 2, p_digits = 3, ...) { diff --git a/R/reduce_parameters.R b/R/reduce_parameters.R index 331b44f55..8e12c852c 100644 --- a/R/reduce_parameters.R +++ b/R/reduce_parameters.R @@ -112,27 +112,27 @@ reduce_parameters.data.frame <- function(x, method = "PCA", n = "max", distance # Get weights / pseudo-loadings (correlations) cormat <- as.data.frame(stats::cor(x = x, y = features)) cormat <- cbind(data.frame(Variable = row.names(cormat)), cormat) - weights <- as.data.frame(.sort_loadings(cormat, cols = 2:ncol(cormat))) + pca_weights <- as.data.frame(.sort_loadings(cormat, cols = 2:ncol(cormat))) if (n == "max") { - weights <- .filter_loadings(weights, threshold = "max", 2:ncol(weights)) - non_empty <- vapply(weights[2:ncol(weights)], function(x) !all(is.na(x)), TRUE) - weights <- weights[c(TRUE, non_empty)] + pca_weights <- .filter_loadings(pca_weights, threshold = "max", 2:ncol(pca_weights)) + non_empty <- vapply(pca_weights[2:ncol(pca_weights)], function(x) !all(is.na(x)), TRUE) + pca_weights <- pca_weights[c(TRUE, non_empty)] features <- features[, non_empty] - weights[is.na(weights)] <- 0 - weights <- .filter_loadings(.sort_loadings(weights, cols = 2:ncol(weights)), threshold = "max", 2:ncol(weights)) + pca_weights[is.na(pca_weights)] <- 0 + pca_weights <- .filter_loadings(.sort_loadings(pca_weights, cols = 2:ncol(pca_weights)), threshold = "max", 2:ncol(pca_weights)) } # Create varnames - varnames <- vapply(weights[2:ncol(weights)], function(x) { - name <- weights$Variable[!is.na(x)] + varnames <- vapply(pca_weights[2:ncol(pca_weights)], function(x) { + name <- pca_weights$Variable[!is.na(x)] weight <- insight::format_value(x[!is.na(x)]) paste0(paste(name, weight, sep = "_"), collapse = "/") }, character(1)) names(features) <- as.character(varnames) # Attributes - attr(features, "loadings") <- weights + attr(features, "loadings") <- pca_weights class(features) <- c("parameters_reduction", class(features)) # Out @@ -143,7 +143,7 @@ reduce_parameters.data.frame <- function(x, method = "PCA", n = "max", distance #' @export reduce_parameters.lm <- function(x, method = "PCA", n = "max", distance = "euclidean", ...) { - data <- reduce_parameters( + model_data <- reduce_parameters( datawizard::to_numeric(insight::get_predictors(x, ...), ...), method = method, n = n, @@ -154,8 +154,8 @@ reduce_parameters.lm <- function(x, method = "PCA", n = "max", distance = "eucli y[insight::find_response(x)] <- insight::get_response(x) y$.row <- NULL - formula <- paste(insight::find_response(x), "~", paste(paste0("`", names(data), "`"), collapse = " + ")) - stats::update(x, formula = formula, data = cbind(data, y)) + new_formula <- paste(insight::find_response(x), "~", paste(paste0("`", names(model_data), "`"), collapse = " + ")) + stats::update(x, formula = new_formula, data = cbind(model_data, y)) } #' @export diff --git a/R/simulate_parameters.R b/R/simulate_parameters.R index 43c4173a2..e26a4e2b5 100644 --- a/R/simulate_parameters.R +++ b/R/simulate_parameters.R @@ -68,9 +68,9 @@ simulate_parameters.default <- function(model, # check for valid input .is_model_valid(model) - 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/standardize_parameters.R b/R/standardize_parameters.R index e7968b6d3..1c3885271 100644 --- a/R/standardize_parameters.R +++ b/R/standardize_parameters.R @@ -575,7 +575,7 @@ print_html.parameters_standardized <- function(x, digits = 2, ...) { deviations[i_missing, ] <- NA } - if (method == "basic") { + if (method == "basic") { # nolint col_dev_resp <- "Deviation_Response_Basic" col_dev_pred <- "Deviation_Basic" } else if (method == "posthoc") { @@ -642,7 +642,7 @@ print_html.parameters_standardized <- function(x, digits = 2, ...) { if (method %in% c("smart", "posthoc")) { cant_posthocsmart <- FALSE - if (mi$is_linear && !colnames(stats::model.frame(model))[1] == insight::find_response(model)) { + if (mi$is_linear && colnames(stats::model.frame(model))[1] != insight::find_response(model)) { can_posthocsmart <- TRUE } @@ -690,7 +690,7 @@ print_html.parameters_standardized <- function(x, digits = 2, ...) { # check if model has a response variable that should not be standardized. info$is_linear && - !info$family == "inverse.gaussian" && + info$family != "inverse.gaussian" && !info$is_survival && !info$is_censored diff --git a/R/utils.R b/R/utils.R index f1238a459..5d2b0e527 100644 --- a/R/utils.R +++ b/R/utils.R @@ -153,7 +153,7 @@ # Almost identical to dynGet(). The difference is that we deparse the expression # because get0() allows symbol only since R 4.1.0 .dynGet <- function(x, - ifnotfound = stop(gettextf("%s not found", sQuote(x)), domain = NA), + ifnotfound = stop(gettextf("%s not found", sQuote(x)), domain = NA, call. = FALSE), minframe = 1L, inherits = FALSE) { x <- insight::safe_deparse(x) diff --git a/R/utils_model_parameters.R b/R/utils_model_parameters.R index 65773eb4d..d5832ff37 100644 --- a/R/utils_model_parameters.R +++ b/R/utils_model_parameters.R @@ -263,20 +263,18 @@ } else if (info$is_count) { coef_col <- "IRR" } - } else { - if (info$is_exponential && identical(info$link_function, "log")) { - coef_col <- "Log-Prevalence" - } else if ((info$is_binomial && info$is_logit) || info$is_ordinal || info$is_multinomial || info$is_categorical) { - coef_col <- "Log-Odds" - } else if (info$is_binomial && !info$is_logit) { - if (info$link_function == "identity") { - coef_col <- "Risk" - } else { - coef_col <- "Log-Risk" - } - } else if (info$is_count) { - coef_col <- "Log-Mean" + } else if (info$is_exponential && identical(info$link_function, "log")) { + coef_col <- "Log-Prevalence" + } else if ((info$is_binomial && info$is_logit) || info$is_ordinal || info$is_multinomial || info$is_categorical) { + coef_col <- "Log-Odds" + } else if (info$is_binomial && !info$is_logit) { + if (info$link_function == "identity") { + coef_col <- "Risk" + } else { + coef_col <- "Log-Risk" } + } else if (info$is_count) { + coef_col <- "Log-Mean" } } @@ -321,13 +319,11 @@ } else if (inherits(model, c("clm", "clm2", "clmm"))) { ## TODO: make sure we catch all ordinal models properly here rows <- !tolower(params$Component) %in% c("location", "scale") - } else { + } else if (is.null(params$Component)) { # don't exponentiate dispersion - if (is.null(params$Component)) { - rows <- seq_len(nrow(params)) - } else { - rows <- !tolower(params$Component) %in% c("dispersion", "residual") - } + rows <- seq_len(nrow(params)) + } else { + rows <- !tolower(params$Component) %in% c("dispersion", "residual") } params[rows, columns] <- exp(params[rows, columns]) if (all(c("Coefficient", "SE") %in% names(params))) { diff --git a/R/utils_pca_efa.R b/R/utils_pca_efa.R index 841df5263..440f74939 100644 --- a/R/utils_pca_efa.R +++ b/R/utils_pca_efa.R @@ -158,33 +158,29 @@ predict.parameters_efa <- function(object, if (isTRUE(keep_na)) { out <- .merge_na(object, out, verbose) } - } else { + } else if ("dataset" %in% names(attri)) { # if we have data, use that for prediction - if ("dataset" %in% names(attri)) { - d <- attri$data_set - d <- d[vapply(d, is.numeric, logical(1))] - out <- as.data.frame(stats::predict(attri$model, newdata = d)) - } else { - insight::format_error( - "Could not retrieve data nor model. Please report an issue on {.url https://github.com/easystats/parameters/issues}." # nolint - ) - } - } - } else { - if (inherits(attri$model, "spca")) { - # https://github.com/erichson/spca/issues/7 - newdata <- newdata[names(attri$model$center)] - if (attri$standardize) { - newdata <- sweep(newdata, MARGIN = 2, STATS = attri$model$center, FUN = "-", check.margin = TRUE) - newdata <- sweep(newdata, MARGIN = 2, STATS = attri$model$scale, FUN = "/", check.margin = TRUE) - } - out <- as.matrix(newdata) %*% as.matrix(attri$model$loadings) - out <- stats::setNames(as.data.frame(out), paste0("Component", seq_len(ncol(out)))) - } else if (inherits(attri$model, c("psych", "fa", "principal"))) { - out <- as.data.frame(stats::predict(attri$model, data = newdata, ...)) + d <- attri$data_set + d <- d[vapply(d, is.numeric, logical(1))] + out <- as.data.frame(stats::predict(attri$model, newdata = d)) } else { - out <- as.data.frame(stats::predict(attri$model, newdata = newdata, ...)) + insight::format_error( + "Could not retrieve data nor model. Please report an issue on {.url https://github.com/easystats/parameters/issues}." # nolint + ) + } + } else if (inherits(attri$model, "spca")) { + # https://github.com/erichson/spca/issues/7 + newdata <- newdata[names(attri$model$center)] + if (attri$standardize) { + newdata <- sweep(newdata, MARGIN = 2, STATS = attri$model$center, FUN = "-", check.margin = TRUE) + newdata <- sweep(newdata, MARGIN = 2, STATS = attri$model$scale, FUN = "/", check.margin = TRUE) } + out <- as.matrix(newdata) %*% as.matrix(attri$model$loadings) + out <- stats::setNames(as.data.frame(out), paste0("Component", seq_len(ncol(out)))) + } else if (inherits(attri$model, c("psych", "fa", "principal"))) { + out <- as.data.frame(stats::predict(attri$model, data = newdata, ...)) + } else { + out <- as.data.frame(stats::predict(attri$model, newdata = newdata, ...)) } if (!is.null(names)) { @@ -343,12 +339,10 @@ print.parameters_omega_summary <- function(x, ...) { } else { table_caption <- c(sprintf("# Loadings from %s (no rotation)", method), "blue") } + } else if (format == "markdown") { + table_caption <- sprintf("Rotated loadings from %s (%s-rotation)", method, rotation_name) } else { - if (format == "markdown") { - table_caption <- sprintf("Rotated loadings from %s (%s-rotation)", method, rotation_name) - } else { - table_caption <- c(sprintf("# Rotated loadings from %s (%s-rotation)", method, rotation_name), "blue") - } + table_caption <- c(sprintf("# Rotated loadings from %s (%s-rotation)", method, rotation_name), "blue") } # footer diff --git a/man/display.parameters_model.Rd b/man/display.parameters_model.Rd index 8c325f32d..fe13979f9 100644 --- a/man/display.parameters_model.Rd +++ b/man/display.parameters_model.Rd @@ -323,6 +323,25 @@ print_html( ) } \dontshow{\}) # examplesIf} +\dontshow{if (require("tinytable") && require("lme4") && require("glmmTMB")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\donttest{ +data(iris) +data(Salamanders, package = "glmmTMB") +m1 <- lm(Sepal.Length ~ Species * Petal.Length, data = iris) +m2 <- lme4::lmer( + Sepal.Length ~ Petal.Length + Petal.Width + (1 | Species), + data = iris +) +m3 <- glmmTMB::glmmTMB( + count ~ spp + mined + (1 | site), + ziformula = ~mined, + family = poisson(), + data = Salamanders +) +out <- compare_parameters(m1, m2, m3, effects = "all", components = "all") +print_table(out) +} +\dontshow{\}) # examplesIf} } \seealso{ \code{\link[=print.parameters_model]{print.parameters_model()}} From befaf58990f3bddd32f2f4466635eff5002be2f5 Mon Sep 17 00:00:00 2001 From: Daniel Date: Tue, 30 Jan 2024 08:24:56 +0100 Subject: [PATCH 08/14] docs --- R/display.R | 50 +++++++++++++++++++-------------- R/methods_mlm.R | 21 ++++++-------- R/print_table.R | 2 +- man/display.parameters_model.Rd | 12 ++++++-- man/model_parameters.mlm.Rd | 21 +++++++------- 5 files changed, 59 insertions(+), 47 deletions(-) diff --git a/R/display.R b/R/display.R index 52a0aa9b7..c3d797af3 100644 --- a/R/display.R +++ b/R/display.R @@ -8,42 +8,50 @@ #' #' @param x An object returned by [`model_parameters()`][model_parameters]. #' @param object An object returned by [`model_parameters()`][model_parameters], -#' [`simulate_parameters()`][simulate_parameters], -#' [`equivalence_test()`][equivalence_test.lm] or -#' [`principal_components()`][principal_components]. +#' [`simulate_parameters()`][simulate_parameters], +#' [`equivalence_test()`][equivalence_test.lm] or +#' [`principal_components()`][principal_components]. #' @param format String, indicating the output format. Can be `"markdown"` -#' or `"html"`. +#' or `"html"`. #' @param align Only applies to HTML tables. May be one of `"left"`, -#' `"right"` or `"center"`. +#' `"right"` or `"center"`. #' @param digits,ci_digits,p_digits Number of digits for rounding or -#' significant figures. May also be `"signif"` to return significant -#' figures or `"scientific"` to return scientific notation. Control the -#' number of digits by adding the value as suffix, e.g. `digits = "scientific4"` -#' to have scientific notation with 4 decimal places, or `digits = "signif5"` -#' for 5 significant figures (see also [signif()]). +#' significant figures. May also be `"signif"` to return significant +#' figures or `"scientific"` to return scientific notation. Control the +#' number of digits by adding the value as suffix, e.g. `digits = "scientific4"` +#' to have scientific notation with 4 decimal places, or `digits = "signif5"` +#' for 5 significant figures (see also [signif()]). #' @param subtitle Table title (same as caption) and subtitle, as strings. If `NULL`, -#' no title or subtitle is printed, unless it is stored as attributes (`table_title`, -#' or its alias `table_caption`, and `table_subtitle`). If `x` is a list of -#' data frames, `caption` may be a list of table captions, one for each table. +#' no title or subtitle is printed, unless it is stored as attributes (`table_title`, +#' or its alias `table_caption`, and `table_subtitle`). If `x` is a list of +#' data frames, `caption` may be a list of table captions, one for each table. #' @param font_size For HTML tables, the font size. #' @param line_padding For HTML tables, the distance (in pixel) between lines. #' @param column_labels Labels of columns for HTML tables. If `NULL`, automatic -#' column names are generated. See 'Examples'. +#' column names are generated. See 'Examples'. #' @inheritParams print.parameters_model #' @inheritParams insight::format_table #' @inheritParams insight::export_table #' @inheritParams compare_parameters #' #' @return If `format = "markdown"`, the return value will be a character -#' vector in markdown-table format. If `format = "html"`, an object of -#' class `gt_tbl`. +#' vector in markdown-table format. If `format = "html"`, an object of +#' class `gt_tbl`. For `print_table()`, an object of class `tinytable` is +#' returned. #' #' @details `display()` is useful when the table-output from functions, -#' which is usually printed as formatted text-table to console, should -#' be formatted for pretty table-rendering in markdown documents, or if -#' knitted from rmarkdown to PDF or Word files. See -#' [vignette](https://easystats.github.io/parameters/articles/model_parameters_formatting.html) -#' for examples. +#' which is usually printed as formatted text-table to console, should +#' be formatted for pretty table-rendering in markdown documents, or if +#' knitted from rmarkdown to PDF or Word files. See +#' [vignette](https://easystats.github.io/parameters/articles/model_parameters_formatting.html) +#' for examples. +#' +#' `print_table()` is a special function for `compare_parameters()` objects, +#' which prints the output as a formatted HTML table. It is still somewhat +#' experimental, thus, only a fixed layout-style is available at the moment +#' (columns for estimates, confidence intervals and p-values). However, it +#' is possible to include other model components, like zero-inflation, or random +#' effects in the table. See 'Examples'. #' #' @seealso [print.parameters_model()] #' diff --git a/R/methods_mlm.R b/R/methods_mlm.R index 5f1c1f2a7..0ec4ee2a1 100644 --- a/R/methods_mlm.R +++ b/R/methods_mlm.R @@ -20,18 +20,15 @@ #' @seealso [insight::standardize_names()] to rename #' columns into a consistent, standardized naming scheme. #' -#' @examples -#' library(parameters) -#' if (require("brglm2", quietly = TRUE)) { -#' data("stemcell") -#' model <- bracl( -#' research ~ as.numeric(religion) + gender, -#' weights = frequency, -#' data = stemcell, -#' type = "ML" -#' ) -#' model_parameters(model) -#' } +#' @examplesIf require("brglm2", quietly = TRUE) +#' data("stemcell", package = "brglm2") +#' model <- brglm2::bracl( +#' research ~ as.numeric(religion) + gender, +#' weights = frequency, +#' data = stemcell, +#' type = "ML" +#' ) +#' model_parameters(model) #' @return A data frame of indices related to the model's parameters. #' @inheritParams simulate_model #' @export diff --git a/R/print_table.R b/R/print_table.R index 9ee2b3846..33182d786 100644 --- a/R/print_table.R +++ b/R/print_table.R @@ -13,7 +13,7 @@ #' family = poisson(), #' data = Salamanders #' ) -#' out <- compare_parameters(m1, m2, m3, effects = "all", components = "all") +#' out <- compare_parameters(m1, m2, m3, effects = "all", component = "all") #' print_table(out) #' } #' @rdname display.parameters_model diff --git a/man/display.parameters_model.Rd b/man/display.parameters_model.Rd index fe13979f9..ef06dec07 100644 --- a/man/display.parameters_model.Rd +++ b/man/display.parameters_model.Rd @@ -280,7 +280,8 @@ to the end.} \value{ If \code{format = "markdown"}, the return value will be a character vector in markdown-table format. If \code{format = "html"}, an object of -class \code{gt_tbl}. +class \code{gt_tbl}. For \code{print_table()}, an object of class \code{tinytable} is +returned. } \description{ Prints tables (i.e. data frame) in different output formats. @@ -295,6 +296,13 @@ be formatted for pretty table-rendering in markdown documents, or if knitted from rmarkdown to PDF or Word files. See \href{https://easystats.github.io/parameters/articles/model_parameters_formatting.html}{vignette} for examples. + +\code{print_table()} is a special function for \code{compare_parameters()} objects, +which prints the output as a formatted HTML table. It is still somewhat +experimental, thus, only a fixed layout-style is available at the moment +(columns for estimates, confidence intervals and p-values). However, it +is possible to include other model components, like zero-inflation, or random +effects in the table. See 'Examples'. } \examples{ \dontshow{if (require("gt", quietly = TRUE)) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} @@ -338,7 +346,7 @@ m3 <- glmmTMB::glmmTMB( family = poisson(), data = Salamanders ) -out <- compare_parameters(m1, m2, m3, effects = "all", components = "all") +out <- compare_parameters(m1, m2, m3, effects = "all", component = "all") print_table(out) } \dontshow{\}) # examplesIf} diff --git a/man/model_parameters.mlm.Rd b/man/model_parameters.mlm.Rd index 8ecefaaca..fb6e86490 100644 --- a/man/model_parameters.mlm.Rd +++ b/man/model_parameters.mlm.Rd @@ -197,17 +197,16 @@ output from \code{model_parameters()} will split the coefficient tables by the different levels of the model's response. } \examples{ -library(parameters) -if (require("brglm2", quietly = TRUE)) { - data("stemcell") - model <- bracl( - research ~ as.numeric(religion) + gender, - weights = frequency, - data = stemcell, - type = "ML" - ) - model_parameters(model) -} +\dontshow{if (require("brglm2", quietly = TRUE)) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +data("stemcell", package = "brglm2") +model <- brglm2::bracl( + research ~ as.numeric(religion) + gender, + weights = frequency, + data = stemcell, + type = "ML" +) +model_parameters(model) +\dontshow{\}) # examplesIf} } \seealso{ \code{\link[insight:standardize_names]{insight::standardize_names()}} to rename From 9f64ec3da4c51dce086f2797f85d2882a8e46b97 Mon Sep 17 00:00:00 2001 From: Daniel Date: Tue, 30 Jan 2024 09:43:04 +0100 Subject: [PATCH 09/14] play with themes --- R/apply_table_style.R | 87 +++++++++++++++++++++++++++++++++ R/display.R | 2 + R/print_table.R | 13 ++++- man/display.parameters_model.Rd | 4 +- 4 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 R/apply_table_style.R diff --git a/R/apply_table_style.R b/R/apply_table_style.R new file mode 100644 index 000000000..f95ac4e41 --- /dev/null +++ b/R/apply_table_style.R @@ -0,0 +1,87 @@ +.apply_table_theme <- function(out, x, theme = "default", row_header_pos = NULL) { + insight::check_if_installed("tinytable") + + switch(theme, + grid = { + out <- tinytable::tt(out, theme = "grid") + }, + striped = { + out <- tinytable::tt(out, theme = "striped") + }, + bootstrap = { + out <- tinytable::tt(out, theme = "bootstrap") + }, + darklines = { + # borders for sub headings + if (!is.null(row_header_pos) && length(row_header_pos) > 1) { + out <- tinytable::style_tt( + out, + i = row_header_pos[2:length(row_header_pos)], + line = "b", + line_color = "#cccccc", + line_width = 0.05 + ) + } + # top table border + out <- tinytable::style_tt( + out, + i = -1, + line = "t", + line_width = 0.2, + line_color = "#444444" + ) + # table border between headers for model names and column headers + out <- tinytable::style_tt( + out, + i = -1, + j = 2:ncol(x), + line = "b", + line_color = "#999999" + ) + # bottom table border + out <- tinytable::style_tt( + out, + i = nrow(x) + length(row_header_pos), + line_width = 0.15, + line = "b", + line_color = "#444444" + ) + }, + # default theme + { + # borders for sub headings + if (!is.null(row_header_pos) && length(row_header_pos) > 1) { + out <- tinytable::style_tt( + out, + i = row_header_pos[2:length(row_header_pos)], + line = "b", + line_color = "#d4d4d4", + line_width = 0.05 + ) + } + # top table border + out <- tinytable::style_tt( + out, + i = -1, + line = "t", + line_color = "#d4d4d4" + ) + # table border between headers for model names and column headers + out <- tinytable::style_tt( + out, + i = -1, + j = 2:ncol(x), + line = "b", + line_color = "#d4d4d4" + ) + # bottom table border + out <- tinytable::style_tt( + out, + i = nrow(x) + length(row_header_pos), + line = "b", + line_color = "#d4d4d4" + ) + } + ) + out +} diff --git a/R/display.R b/R/display.R index c3d797af3..deb95ca05 100644 --- a/R/display.R +++ b/R/display.R @@ -29,6 +29,8 @@ #' @param line_padding For HTML tables, the distance (in pixel) between lines. #' @param column_labels Labels of columns for HTML tables. If `NULL`, automatic #' column names are generated. See 'Examples'. +#' @param theme String, indicating the table theme. Can be one of `"default"`, +#' `"grid"`, `"striped"`, `"bootstrap"` or `"darklines"`. #' @inheritParams print.parameters_model #' @inheritParams insight::format_table #' @inheritParams insight::export_table diff --git a/R/print_table.R b/R/print_table.R index 33182d786..09daa3f43 100644 --- a/R/print_table.R +++ b/R/print_table.R @@ -18,7 +18,7 @@ #' } #' @rdname display.parameters_model #' @export -print_table <- function(x, digits = 2, p_digits = 3, ...) { +print_table <- function(x, digits = 2, p_digits = 3, theme = "default", ...) { insight::check_if_installed(c("datawizard", "tinytable")) if (!inherits(x, "compare_parameters")) { @@ -48,6 +48,15 @@ print_table <- function(x, digits = 2, p_digits = 3, ...) { x$Group <- NULL } + # check if we have only have fixed effects, and if so, remove column + if (!is.null(x$Effects) && all(x$Effects == "fixed")) { + x$Effects <- NULL + } + # check if we have only have conditional component, and if so, remove column + if (!is.null(x$Component) && all(x$Component == "conditional")) { + x$Component <- NULL + } + # check if we have models with extra components (e.g., zero-inflated models) # if so, we need to create a group variable, so we can include subheaders in # the table, and we want to re-arrange rows @@ -153,6 +162,8 @@ print_table <- function(x, digits = 2, p_digits = 3, ...) { } else { out <- tinytable::group_tt(out, j = col_groups) } + # style table + out <- .apply_table_theme(out, x, theme = theme, row_header_pos = row_header_pos) # workaround, to make sure HTML is default output m <- attr(out, "tinytable_meta") m$output <- "html" diff --git a/man/display.parameters_model.Rd b/man/display.parameters_model.Rd index ef06dec07..2c2c65d90 100644 --- a/man/display.parameters_model.Rd +++ b/man/display.parameters_model.Rd @@ -129,7 +129,7 @@ ... ) -print_table(x, digits = 2, p_digits = 3, ...) +print_table(x, digits = 2, p_digits = 3, style = "default", ...) } \arguments{ \item{object}{An object returned by \code{\link[=model_parameters]{model_parameters()}}, @@ -276,6 +276,8 @@ row". A possible use case might be to emphasize focal predictors and control variables, see 'Examples'. Parameters will be re-ordered according to the order used in \code{groups}, while all non-matching parameters will be added to the end.} + +\item{style}{String, indicating the table style. Currently, only \code{"default"}} } \value{ If \code{format = "markdown"}, the return value will be a character From 1541a61b909419bfafb9275be257646fb3ae9288 Mon Sep 17 00:00:00 2001 From: Daniel Date: Tue, 30 Jan 2024 09:43:21 +0100 Subject: [PATCH 10/14] rename --- R/{apply_table_style.R => apply_table_theme.R} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename R/{apply_table_style.R => apply_table_theme.R} (100%) diff --git a/R/apply_table_style.R b/R/apply_table_theme.R similarity index 100% rename from R/apply_table_style.R rename to R/apply_table_theme.R From bed121bd8d90961147c513a91cada26f2b0e250e Mon Sep 17 00:00:00 2001 From: Daniel Date: Tue, 30 Jan 2024 09:43:50 +0100 Subject: [PATCH 11/14] update docs --- man/display.parameters_model.Rd | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/man/display.parameters_model.Rd b/man/display.parameters_model.Rd index 2c2c65d90..1a36422f7 100644 --- a/man/display.parameters_model.Rd +++ b/man/display.parameters_model.Rd @@ -129,7 +129,7 @@ ... ) -print_table(x, digits = 2, p_digits = 3, style = "default", ...) +print_table(x, digits = 2, p_digits = 3, theme = "default", ...) } \arguments{ \item{object}{An object returned by \code{\link[=model_parameters]{model_parameters()}}, @@ -277,7 +277,8 @@ variables, see 'Examples'. Parameters will be re-ordered according to the order used in \code{groups}, while all non-matching parameters will be added to the end.} -\item{style}{String, indicating the table style. Currently, only \code{"default"}} +\item{theme}{String, indicating the table theme. Can be one of \code{"default"}, +\code{"grid"}, \code{"striped"}, \code{"bootstrap"} or \code{"darklines"}.} } \value{ If \code{format = "markdown"}, the return value will be a character From 98530dcda3f1c789a4317ae36a7937671d6976c1 Mon Sep 17 00:00:00 2001 From: Daniel Date: Tue, 30 Jan 2024 09:55:44 +0100 Subject: [PATCH 12/14] use insight function --- DESCRIPTION | 1 + R/apply_table_theme.R | 87 ------------------------------------------- R/print_table.R | 2 +- 3 files changed, 2 insertions(+), 88 deletions(-) delete mode 100644 R/apply_table_theme.R diff --git a/DESCRIPTION b/DESCRIPTION index 71a9d4387..dbe8aee4d 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -216,3 +216,4 @@ Config/Needs/website: r-lib/pkgdown, easystats/easystatstemplate Config/rcmdcheck/ignore-inconsequential-notes: true +Remotes: easystats/insight diff --git a/R/apply_table_theme.R b/R/apply_table_theme.R deleted file mode 100644 index f95ac4e41..000000000 --- a/R/apply_table_theme.R +++ /dev/null @@ -1,87 +0,0 @@ -.apply_table_theme <- function(out, x, theme = "default", row_header_pos = NULL) { - insight::check_if_installed("tinytable") - - switch(theme, - grid = { - out <- tinytable::tt(out, theme = "grid") - }, - striped = { - out <- tinytable::tt(out, theme = "striped") - }, - bootstrap = { - out <- tinytable::tt(out, theme = "bootstrap") - }, - darklines = { - # borders for sub headings - if (!is.null(row_header_pos) && length(row_header_pos) > 1) { - out <- tinytable::style_tt( - out, - i = row_header_pos[2:length(row_header_pos)], - line = "b", - line_color = "#cccccc", - line_width = 0.05 - ) - } - # top table border - out <- tinytable::style_tt( - out, - i = -1, - line = "t", - line_width = 0.2, - line_color = "#444444" - ) - # table border between headers for model names and column headers - out <- tinytable::style_tt( - out, - i = -1, - j = 2:ncol(x), - line = "b", - line_color = "#999999" - ) - # bottom table border - out <- tinytable::style_tt( - out, - i = nrow(x) + length(row_header_pos), - line_width = 0.15, - line = "b", - line_color = "#444444" - ) - }, - # default theme - { - # borders for sub headings - if (!is.null(row_header_pos) && length(row_header_pos) > 1) { - out <- tinytable::style_tt( - out, - i = row_header_pos[2:length(row_header_pos)], - line = "b", - line_color = "#d4d4d4", - line_width = 0.05 - ) - } - # top table border - out <- tinytable::style_tt( - out, - i = -1, - line = "t", - line_color = "#d4d4d4" - ) - # table border between headers for model names and column headers - out <- tinytable::style_tt( - out, - i = -1, - j = 2:ncol(x), - line = "b", - line_color = "#d4d4d4" - ) - # bottom table border - out <- tinytable::style_tt( - out, - i = nrow(x) + length(row_header_pos), - line = "b", - line_color = "#d4d4d4" - ) - } - ) - out -} diff --git a/R/print_table.R b/R/print_table.R index 09daa3f43..029f40c3a 100644 --- a/R/print_table.R +++ b/R/print_table.R @@ -163,7 +163,7 @@ print_table <- function(x, digits = 2, p_digits = 3, theme = "default", ...) { out <- tinytable::group_tt(out, j = col_groups) } # style table - out <- .apply_table_theme(out, x, theme = theme, row_header_pos = row_header_pos) + out <- insight::apply_table_theme(out, x, theme = theme, sub_header_positions = row_header_pos) # workaround, to make sure HTML is default output m <- attr(out, "tinytable_meta") m$output <- "html" From 32dd1576646cf340bb8fb31fadbb4f7452b4dfb7 Mon Sep 17 00:00:00 2001 From: Daniel Date: Tue, 30 Jan 2024 12:27:43 +0100 Subject: [PATCH 13/14] fix --- R/format_parameters.R | 54 ++++++++++----------- R/utils_model_parameters.R | 2 +- tests/testthat/test-model_parameters.vgam.R | 6 +-- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/R/format_parameters.R b/R/format_parameters.R index e90c8ef90..24510135a 100644 --- a/R/format_parameters.R +++ b/R/format_parameters.R @@ -68,7 +68,7 @@ format_parameters.parameters_model <- function(model, ...) { .format_parameter_default <- function(model, effects = "fixed", brackets = c("[", "]"), ...) { - original_names <- names <- insight::find_parameters(model, effects = effects, flatten = TRUE) + original_names <- parameter_names <- insight::find_parameters(model, effects = effects, flatten = TRUE) # save some time, if model info is passed as argument dot_args <- list(...) @@ -85,7 +85,7 @@ format_parameters.parameters_model <- function(model, ...) { # quick fix, for multivariate response models, we use # info from first model only - if (insight::is_multivariate(model) && !"is_zero_inflated" %in% names(info)) { + if (insight::is_multivariate(model) && !"is_zero_inflated" %in% names(info) && !inhertis(model, c("vgam", "vglm"))) { info <- info[[1]] } @@ -100,19 +100,19 @@ format_parameters.parameters_model <- function(model, ...) { # special handling hurdle- and zeroinfl-models --------------------- if (isTRUE(info$is_zero_inflated) || isTRUE(info$is_hurdle)) { - names <- gsub("^(count_|zero_)", "", names) + parameter_names <- gsub("^(count_|zero_)", "", parameter_names) types$Parameter <- gsub("^(count_|zero_)", "", types$Parameter) } # special handling polr --------------------- if (inherits(model, "polr")) { original_names <- gsub("Intercept: ", "", original_names, fixed = TRUE) - names <- gsub("Intercept: ", "", names, fixed = TRUE) + parameter_names <- gsub("Intercept: ", "", parameter_names, fixed = TRUE) } # special handling bracl --------------------- if (inherits(model, "bracl")) { - names <- gsub("(.*):(.*)", "\\2", names) + parameter_names <- gsub("(.*):(.*)", "\\2", parameter_names) } # special handling DirichletRegModel --------------------- @@ -121,11 +121,11 @@ format_parameters.parameters_model <- function(model, ...) { cf <- stats::coef(model) if (model$parametrization == "common") { pattern <- paste0("(", paste(model$varnames, collapse = "|"), ")\\.(.*)") - dirich_names <- names <- gsub(pattern, "\\2", names(unlist(cf))) + dirich_names <- parameter_names <- gsub(pattern, "\\2", names(unlist(cf))) } else { - dirich_names <- names <- gsub("(.*)\\.(.*)\\.(.*)", "\\3", names(unlist(cf))) + dirich_names <- parameter_names <- gsub("(.*)\\.(.*)\\.(.*)", "\\3", names(unlist(cf))) } - original_names <- names + original_names <- parameter_names if (!is.null(dirich_names)) { types$Parameter <- dirich_names } @@ -133,7 +133,7 @@ format_parameters.parameters_model <- function(model, ...) { # remove "as.factor()", "log()" etc. from parameter names - names <- .clean_parameter_names(names) + parameter_names <- .clean_parameter_names(parameter_names) for (i in seq_len(nrow(types))) { @@ -175,7 +175,7 @@ format_parameters.parameters_model <- function(model, ...) { ) } } - names[i] <- .format_interaction( + parameter_names[i] <- .format_interaction( components = components, type = types[i, "Type"], is_nested = is_nested, @@ -185,7 +185,7 @@ format_parameters.parameters_model <- function(model, ...) { } else { # No interaction type <- types[i, ] - names[i] <- .format_parameter( + parameter_names[i] <- .format_parameter( name, variable = type$Variable, type = type$Type, @@ -196,9 +196,9 @@ format_parameters.parameters_model <- function(model, ...) { } # do some final formatting, like replacing underscores or dots with whitespace. - names <- gsub("(\\.|_)(?![^\\[]*\\])", " ", names, perl = TRUE) + parameter_names <- gsub("(\\.|_)(?![^\\[]*\\])", " ", parameter_names, perl = TRUE) # remove double spaces - names <- gsub(" ", " ", names, fixed = TRUE) + parameter_names <- gsub(" ", " ", parameter_names, fixed = TRUE) # "types$Parameter" here is cleaned, i.e. patterns like "log()", "as.factor()" # etc. are removed. However, these patterns are needed in "format_table()", @@ -207,8 +207,8 @@ format_parameters.parameters_model <- function(model, ...) { # so output will be NA resp. blank fields... Thus, I think we should use # the original parameter-names here. - names(names) <- original_names # types$Parameter - names + names(parameter_names) <- original_names # types$Parameter + parameter_names } @@ -361,7 +361,7 @@ format_parameters.parameters_model <- function(model, ...) { # replace pretty names with value labels, when present --------------- .format_value_labels <- function(params, model = NULL) { - labels <- NULL + pretty_labels <- NULL if (is.null(model)) { model <- .get_object(params) } @@ -390,9 +390,9 @@ format_parameters.parameters_model <- function(model, ...) { out <- attr(vec, "label", exact = TRUE) } if (is.null(out)) { - return(i) + i } else { - return(out) + out } }) @@ -406,7 +406,7 @@ format_parameters.parameters_model <- function(model, ...) { # name elements names(lbs) <- names(preds) <- colnames(mf) - labels <- .safe(stats::setNames( + pretty_labels <- .safe(stats::setNames( unlist(lbs, use.names = FALSE), unlist(preds, use.names = FALSE) )) @@ -415,7 +415,7 @@ format_parameters.parameters_model <- function(model, ...) { pn <- attributes(params)$pretty_names # replace former pretty names with labels, if we have any labels # (else, default pretty names are returned) - if (!is.null(labels)) { + if (!is.null(pretty_labels)) { # check if we have any interactions, and if so, create combined labels interactions <- pn[grepl(":", names(pn), fixed = TRUE)] if (length(interactions)) { @@ -424,23 +424,23 @@ format_parameters.parameters_model <- function(model, ...) { # extract single coefficient names from interaction term out <- unlist(strsplit(i, ":", fixed = TRUE)) # combine labels - labs <- c(labs, paste0(sapply(out, function(l) labels[l]), collapse = " * ")) + labs <- c(labs, paste0(sapply(out, function(l) pretty_labels[l]), collapse = " * ")) } # add interaction terms to labels string names(labs) <- names(interactions) - labels <- c(labels, labs) + pretty_labels <- c(pretty_labels, labs) } # make sure "invalid" labels are ignored - common_labels <- intersect(names(labels), names(pn)) - pn[common_labels] <- labels[common_labels] + common_labels <- intersect(names(pretty_labels), names(pn)) + pn[common_labels] <- pretty_labels[common_labels] } - labels <- pn + pretty_labels <- pn } # missing labels return original parameter name (e.g., variance components in mixed models) out <- stats::setNames(params$Parameter, params$Parameter) - labels <- labels[names(labels) %in% params$Parameter] - out[match(names(labels), params$Parameter)] <- labels + pretty_labels <- pretty_labels[names(pretty_labels) %in% params$Parameter] + out[match(names(pretty_labels), params$Parameter)] <- pretty_labels out } diff --git a/R/utils_model_parameters.R b/R/utils_model_parameters.R index d5832ff37..ac26ec75d 100644 --- a/R/utils_model_parameters.R +++ b/R/utils_model_parameters.R @@ -27,7 +27,7 @@ # for simplicity, we just use the model information from the first formula # when we have multivariate response models... - if (insight::is_multivariate(model) && !"is_zero_inflated" %in% names(info)) { + if (insight::is_multivariate(model) && !"is_zero_inflated" %in% names(info) && !inhertis(model, c("vgam", "vglm"))) { info <- info[[1]] } diff --git a/tests/testthat/test-model_parameters.vgam.R b/tests/testthat/test-model_parameters.vgam.R index f1f5925c3..5c7d57243 100644 --- a/tests/testthat/test-model_parameters.vgam.R +++ b/tests/testthat/test-model_parameters.vgam.R @@ -26,7 +26,7 @@ test_that("model_parameters.vgam", { skip("TODO: model_parameters doesn't work with 'VGAM::' in the formula") params <- suppressWarnings(model_parameters(m1)) expect_equal(params$Coefficient, as.vector(m1@coefficients[params$Parameter]), tolerance = 1e-3) - expect_equal(params$Parameter, c("(Intercept):1", "(Intercept):2", "exposure.time", "s(let)")) + expect_identical(params$Parameter, c("(Intercept):1", "(Intercept):2", "exposure.time", "s(let)")) expect_equal(params$df, c(NA, NA, NA, 2.6501), tolerance = 1e-3) expect_equal(as.vector(na.omit(params$df)), as.vector(m1@nl.df), tolerance = 1e-3) }) @@ -35,10 +35,10 @@ test_that("model_parameters.vgam", { skip("TODO: model_parameters doesn't work with 'VGAM::' in the formula") params <- suppressWarnings(model_parameters(m2)) expect_equal(params$Coefficient, as.vector(m2@coefficients[params$Parameter]), tolerance = 1e-3) - expect_equal(params$Parameter, c("(Intercept)", "beitaw", "corlae", "s(altitude, df = 2)", "s(x)")) + expect_identical(params$Parameter, c("(Intercept)", "beitaw", "corlae", "s(altitude, df = 2)", "s(x)")) expect_equal(params$df, c(NA, NA, NA, 0.82686, 2.8054), tolerance = 1e-3) expect_equal(as.vector(na.omit(params$df)), as.vector(m2@nl.df), tolerance = 1e-3) - expect_equal(colnames(params), c( + expect_named(params, c( "Parameter", "Coefficient", "SE", "CI", "CI_low", "CI_high", "Chi2", "df_error", "p", "Component" )) From 51546ad6c11b9d79c05e2c1c3c0bb438c07b4ad5 Mon Sep 17 00:00:00 2001 From: Daniel Date: Tue, 30 Jan 2024 14:16:02 +0100 Subject: [PATCH 14/14] typo --- R/format_parameters.R | 2 +- R/utils_model_parameters.R | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/R/format_parameters.R b/R/format_parameters.R index 24510135a..b425adc1b 100644 --- a/R/format_parameters.R +++ b/R/format_parameters.R @@ -85,7 +85,7 @@ format_parameters.parameters_model <- function(model, ...) { # quick fix, for multivariate response models, we use # info from first model only - if (insight::is_multivariate(model) && !"is_zero_inflated" %in% names(info) && !inhertis(model, c("vgam", "vglm"))) { + if (insight::is_multivariate(model) && !"is_zero_inflated" %in% names(info) && !inherits(model, c("vgam", "vglm"))) { info <- info[[1]] } diff --git a/R/utils_model_parameters.R b/R/utils_model_parameters.R index ac26ec75d..68832056e 100644 --- a/R/utils_model_parameters.R +++ b/R/utils_model_parameters.R @@ -27,7 +27,7 @@ # for simplicity, we just use the model information from the first formula # when we have multivariate response models... - if (insight::is_multivariate(model) && !"is_zero_inflated" %in% names(info) && !inhertis(model, c("vgam", "vglm"))) { + if (insight::is_multivariate(model) && !"is_zero_inflated" %in% names(info) && !inherits(model, c("vgam", "vglm"))) { info <- info[[1]] }