diff --git a/DESCRIPTION b/DESCRIPTION index 2f3587b2b..2faafe6c3 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Type: Package Package: parameters Title: Processing of Model Parameters -Version: 0.29.2 +Version: 0.29.2.1 Authors@R: c(person(given = "Daniel", family = "Lüdecke", diff --git a/NEWS.md b/NEWS.md index 60d8134e6..8c1faf8b9 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,10 @@ +# parameters (devel) + +## Changes + +* Logical variables are now properly formatted when pretty value labels are + printed. + # parameters 0.29.2 ## Changes diff --git a/R/format_parameters.R b/R/format_parameters.R index c9be9a858..9886a5af6 100644 --- a/R/format_parameters.R +++ b/R/format_parameters.R @@ -242,6 +242,11 @@ format_parameters.parameters_model <- function(model, ...) { name <- .format_factor(name = name, variable = variable, brackets = brackets) } + # Logical + if (type == "logical") { + name <- .format_logical(name = name, brackets = brackets) + } + # Polynomials if (type %in% c("poly", "poly_raw")) { name <- .format_poly( @@ -394,6 +399,12 @@ format_parameters.parameters_model <- function(model, ...) { } +#' @keywords internal +.format_logical <- function(name, brackets = c("[", "]")) { + paste0(sub("TRUE$", "", name), " ", brackets[1], "TRUE", brackets[2]) +} + + #' @keywords internal .format_log <- function(name, variable, type, brackets = c("[", "]")) { paste0(variable, " ", brackets[1], gsub("(.*)\\((.*)\\)", "\\1", name), brackets[2]) @@ -463,7 +474,7 @@ format_parameters.parameters_model <- function(model, ...) { factor_terms ) for (k in seq_along(factor_terms)) { - ft <- factor_terms[k] # e.g. "factor(cyl)" + ft <- factor_terms[k] # e.g. "factor(cyl)" orig <- cleaned_terms[k] # e.g. "cyl" if (orig %in% colnames(mf) && !ft %in% colnames(mf)) { orig_label <- attr(mf[[orig]], "label", exact = TRUE) diff --git a/R/parameters_type.R b/R/parameters_type.R index 334157cd8..ab119fe0f 100644 --- a/R/parameters_type.R +++ b/R/parameters_type.R @@ -215,6 +215,11 @@ parameters_type <- function(model, ...) { } else if (cleaned_name %in% reference$numeric) { return(c("numeric", "Association", name, name, NA, NA)) + # Logicals + } else if (sub("TRUE$", "", cleaned_name) %in% reference$logical) { + cleaned_name <- sub("TRUE$", "", cleaned_name) + return(c("logical", "Difference", name, cleaned_name, "TRUE", NA)) + # Ordered factors } else if (is.ordered(data[[cleaned_ordered_name]])) { fac <- reference$levels_parent[match(cleaned_name, reference$levels)] @@ -327,7 +332,7 @@ parameters_type <- function(model, ...) { .check_for_numerics <- function(x) { is.numeric(x) && !isTRUE(attributes(x)$factor) } - out$numeric <- names(data[vapply(data, .check_for_numerics, TRUE)]) + out$numeric <- names(data)[vapply(data, .check_for_numerics, TRUE)] # get contrast coding contrast_coding <- .safe(model$contrasts) @@ -368,12 +373,12 @@ parameters_type <- function(model, ...) { } # Ordered factors - out$ordered <- names(data[vapply(data, is.ordered, TRUE)]) + out$ordered <- names(data)[vapply(data, is.ordered, TRUE)] # Factors - out$factor <- names(data[ + out$factor <- names(data)[ vapply(data, is.factor, TRUE) | vapply(data, is.character, TRUE) - ]) + ] out$levels <- NA out$levels_parent <- NA @@ -427,5 +432,8 @@ parameters_type <- function(model, ...) { out$levels <- out$levels[!is.na(out$levels)] out$levels_parent <- out$levels_parent[!is.na(out$levels_parent)] + # Logical + out$logical <- names(data)[vapply(data, is.logical, TRUE)] + out } diff --git a/R/utils_cleaners.R b/R/utils_cleaners.R index 3ef4af17e..1878ce6ca 100644 --- a/R/utils_cleaners.R +++ b/R/utils_cleaners.R @@ -11,15 +11,19 @@ # remove them here and clean/prepare them in ".parameters_type_basic()". # for formatting / printing, refer to ".format_parameter()". + # fmt: skip pattern <- if (full) { c( - "as.factor", "as.numeric", "as.ordered", "factor", "ordered", "offset", - "lag", "diff", "catg", "matrx", "pol", "strata", "strat", "scale", + "as.factor", "as.numeric", "as.ordered", "as.logical", "factor", "ordered", + "offset", "lag", "diff", "catg", "matrx", "pol", "strata", "strat", "scale", "scored", "interaction", "lsp", "pb", "lo", "t2", "te", "ti", "tt", "mi", "mo", "gp" ) } else { - c("as.factor", "as.numeric", "as.ordered", "factor", "ordered", "catg", "interaction") + c( + "as.factor", "as.numeric", "as.ordered", "as.logical", "factor", "ordered", + "catg", "interaction" + ) } for (j in seq_along(pattern)) { @@ -31,7 +35,12 @@ x <- insight::trim_ws(sub("offset\\(([^-+ )]*)\\)(.*)", "\\1\\2", x)) # some exceptions here... } else if (full && pattern[j] == "scale" && any(grepl("scale(", x, fixed = TRUE))) { - x[grepl("scale(", x, fixed = TRUE)] <- insight::clean_names(grep("scale(", x, fixed = TRUE, value = TRUE)) + x[grepl("scale(", x, fixed = TRUE)] <- insight::clean_names(grep( + "scale(", + x, + fixed = TRUE, + value = TRUE + )) } else if (any(grepl(pattern[j], x, fixed = TRUE))) { p <- paste0(pattern[j], "\\(((\\w|\\.)*)\\)(.*)") x <- insight::trim_ws(sub(p, "\\1\\3", x)) diff --git a/tests/testthat/test-factor_analysis.R b/tests/testthat/test-factor_analysis.R index c62227fd1..20ac69d2b 100644 --- a/tests/testthat/test-factor_analysis.R +++ b/tests/testthat/test-factor_analysis.R @@ -117,7 +117,7 @@ test_that("factor_analysis", { out <- suppressWarnings(factor_analysis(r_mat, n_obs = n_mat, n = 2)) expect_identical(dim(out), c(28L, 5L)) - expect_named(out, c("Variable", "MR1", "MR2", "Complexity", "Uniqueness")) + expect_named(out, c("Variable", "MR2", "MR1", "Complexity", "Uniqueness")) n_mat <- matrix(0, nrow = n - 2, ncol = n - 2) diag(n_mat) <- 1 diff --git a/tests/testthat/test-format_model_parameters.R b/tests/testthat/test-format_model_parameters.R index 6e007f864..ee0b830a6 100644 --- a/tests/testthat/test-format_model_parameters.R +++ b/tests/testthat/test-format_model_parameters.R @@ -1,178 +1,250 @@ skip_if_not_installed("withr") # make sure we have the correct interaction mark for tests -withr::with_options( - list(parameters_interaction = "*"), - { - test_that("format_model_parameters-1", { - m <- lm(mpg ~ qsec:wt + wt:drat, data = mtcars) - expect_identical(unname(format_parameters(m)), c("(Intercept)", "qsec * wt", "wt * drat")) - }) - - test_that("format_model_parameters-2", { - m <- lm(mpg ~ qsec:wt + wt / drat, data = mtcars) - expect_identical(unname(format_parameters(m)), c("(Intercept)", "wt", "qsec * wt", "wt * drat")) - }) - - test_that("format_model_parameters-3", { - m <- lm(mpg ~ qsec:wt + wt:drat + wt, data = mtcars) - expect_identical(unname(format_parameters(m)), c("(Intercept)", "wt", "qsec * wt", "wt * drat")) - }) - - test_that("format_model_parameters-4", { - m <- lm(mpg ~ qsec:wt + wt / drat + wt, data = mtcars) - expect_identical(unname(format_parameters(m)), c("(Intercept)", "wt", "qsec * wt", "wt * drat")) - }) - - test_that("format_model_parameters-5", { - m <- lm(mpg ~ qsec * wt + wt:drat + wt, data = mtcars) - expect_identical(unname(format_parameters(m)), c("(Intercept)", "qsec", "wt", "qsec * wt", "wt * drat")) - }) - - test_that("format_model_parameters-6", { - m <- lm(mpg ~ wt + qsec + wt:qsec, data = mtcars) - expect_identical(unname(format_parameters(m)), c("(Intercept)", "wt", "qsec", "wt * qsec")) - }) - - test_that("format_model_parameters-7", { - m <- lm(Sepal.Width ~ Species * Petal.Length, data = iris) - expect_identical( - unname(format_parameters(m)), - c( - "(Intercept)", "Species [versicolor]", "Species [virginica]", - "Petal Length", "Species [versicolor] * Petal Length", - "Species [virginica] * Petal Length" - ) +withr::with_options(list(parameters_interaction = "*"), { + test_that("format_model_parameters-1", { + m <- lm(mpg ~ qsec:wt + wt:drat, data = mtcars) + expect_identical( + unname(format_parameters(m)), + c("(Intercept)", "qsec * wt", "wt * drat") + ) + }) + + test_that("format_model_parameters-2", { + m <- lm(mpg ~ qsec:wt + wt / drat, data = mtcars) + expect_identical( + unname(format_parameters(m)), + c("(Intercept)", "wt", "qsec * wt", "wt * drat") + ) + }) + + test_that("format_model_parameters-3", { + m <- lm(mpg ~ qsec:wt + wt:drat + wt, data = mtcars) + expect_identical( + unname(format_parameters(m)), + c("(Intercept)", "wt", "qsec * wt", "wt * drat") + ) + }) + + test_that("format_model_parameters-4", { + m <- lm(mpg ~ qsec:wt + wt / drat + wt, data = mtcars) + expect_identical( + unname(format_parameters(m)), + c("(Intercept)", "wt", "qsec * wt", "wt * drat") + ) + }) + + test_that("format_model_parameters-5", { + m <- lm(mpg ~ qsec * wt + wt:drat + wt, data = mtcars) + expect_identical( + unname(format_parameters(m)), + c("(Intercept)", "qsec", "wt", "qsec * wt", "wt * drat") + ) + }) + + test_that("format_model_parameters-6", { + m <- lm(mpg ~ wt + qsec + wt:qsec, data = mtcars) + expect_identical( + unname(format_parameters(m)), + c("(Intercept)", "wt", "qsec", "wt * qsec") + ) + }) + + test_that("format_model_parameters-7", { + m <- lm(Sepal.Width ~ Species * Petal.Length, data = iris) + expect_identical( + unname(format_parameters(m)), + c( + "(Intercept)", + "Species [versicolor]", + "Species [virginica]", + "Petal Length", + "Species [versicolor] * Petal Length", + "Species [virginica] * Petal Length" ) - }) - - test_that("format_model_parameters-8", { - m <- lm(Sepal.Width ~ Species:Petal.Length, data = iris) - expect_identical( - unname(format_parameters(m)), - c( - "(Intercept)", "Species [setosa] * Petal Length", - "Species [versicolor] * Petal Length", - "Species [virginica] * Petal Length" - ) + ) + }) + + test_that("format_model_parameters-8", { + m <- lm(Sepal.Width ~ Species:Petal.Length, data = iris) + expect_identical( + unname(format_parameters(m)), + c( + "(Intercept)", + "Species [setosa] * Petal Length", + "Species [versicolor] * Petal Length", + "Species [virginica] * Petal Length" ) - }) - - test_that("format_model_parameters-9", { - m <- lm(Sepal.Width ~ Species / Petal.Length, data = iris) - expect_identical( - unname(format_parameters(m)), - c( - "(Intercept)", "Species [versicolor]", "Species [virginica]", - "Species [setosa] * Petal Length", "Species [versicolor] * Petal Length", - "Species [virginica] * Petal Length" - ) + ) + }) + + test_that("format_model_parameters-9", { + m <- lm(Sepal.Width ~ Species / Petal.Length, data = iris) + expect_identical( + unname(format_parameters(m)), + c( + "(Intercept)", + "Species [versicolor]", + "Species [virginica]", + "Species [setosa] * Petal Length", + "Species [versicolor] * Petal Length", + "Species [virginica] * Petal Length" ) - }) - - test_that("format_model_parameters-10", { - m <- lm(Sepal.Width ~ Species * Petal.Length + Species, data = iris) - expect_identical( - unname(format_parameters(m)), - c( - "(Intercept)", "Species [versicolor]", "Species [virginica]", - "Petal Length", "Species [versicolor] * Petal Length", - "Species [virginica] * Petal Length" - ) + ) + }) + + test_that("format_model_parameters-10", { + m <- lm(Sepal.Width ~ Species * Petal.Length + Species, data = iris) + expect_identical( + unname(format_parameters(m)), + c( + "(Intercept)", + "Species [versicolor]", + "Species [virginica]", + "Petal Length", + "Species [versicolor] * Petal Length", + "Species [virginica] * Petal Length" ) - }) - - test_that("format_model_parameters-11", { - m <- lm(Sepal.Width ~ Species:Petal.Length + Species, data = iris) - expect_identical( - unname(format_parameters(m)), - c( - "(Intercept)", "Species [versicolor]", "Species [virginica]", - "Species [setosa] * Petal Length", "Species [versicolor] * Petal Length", - "Species [virginica] * Petal Length" - ) + ) + }) + + test_that("format_model_parameters-11", { + m <- lm(Sepal.Width ~ Species:Petal.Length + Species, data = iris) + expect_identical( + unname(format_parameters(m)), + c( + "(Intercept)", + "Species [versicolor]", + "Species [virginica]", + "Species [setosa] * Petal Length", + "Species [versicolor] * Petal Length", + "Species [virginica] * Petal Length" ) - }) - - test_that("format_model_parameters-12", { - m <- lm(Sepal.Width ~ Species / Petal.Length + Species, data = iris) - expect_identical( - unname(format_parameters(m)), - c( - "(Intercept)", "Species [versicolor]", "Species [virginica]", - "Species [setosa] * Petal Length", "Species [versicolor] * Petal Length", - "Species [virginica] * Petal Length" - ) + ) + }) + + test_that("format_model_parameters-12", { + m <- lm(Sepal.Width ~ Species / Petal.Length + Species, data = iris) + expect_identical( + unname(format_parameters(m)), + c( + "(Intercept)", + "Species [versicolor]", + "Species [virginica]", + "Species [setosa] * Petal Length", + "Species [versicolor] * Petal Length", + "Species [virginica] * Petal Length" ) - }) - - test_that("format_model_parameters-13", { - m <- lm(Sepal.Width ~ Species * Petal.Length + Petal.Length, data = iris) - expect_identical( - unname(format_parameters(m)), - c( - "(Intercept)", "Species [versicolor]", "Species [virginica]", - "Petal Length", "Species [versicolor] * Petal Length", "Species [virginica] * Petal Length" - ) + ) + }) + + test_that("format_model_parameters-13", { + m <- lm(Sepal.Width ~ Species * Petal.Length + Petal.Length, data = iris) + expect_identical( + unname(format_parameters(m)), + c( + "(Intercept)", + "Species [versicolor]", + "Species [virginica]", + "Petal Length", + "Species [versicolor] * Petal Length", + "Species [virginica] * Petal Length" ) - }) - - test_that("format_model_parameters-14", { - m <- lm(Sepal.Width ~ Species:Petal.Length + Petal.Length, data = iris) - expect_identical( - unname(format_parameters(m)), - c( - "(Intercept)", "Petal Length", "Species [versicolor] * Petal Length", - "Species [virginica] * Petal Length" - ) + ) + }) + + test_that("format_model_parameters-14", { + m <- lm(Sepal.Width ~ Species:Petal.Length + Petal.Length, data = iris) + expect_identical( + unname(format_parameters(m)), + c( + "(Intercept)", + "Petal Length", + "Species [versicolor] * Petal Length", + "Species [virginica] * Petal Length" ) - }) - - test_that("format_model_parameters-15", { - m <- lm(Sepal.Width ~ Species / Petal.Length + Petal.Length, data = iris) - expect_identical( - unname(format_parameters(m)), - c( - "(Intercept)", "Species [versicolor]", "Species [virginica]", - "Petal Length", "Species [versicolor] * Petal Length", "Species [virginica] * Petal Length" - ) + ) + }) + + test_that("format_model_parameters-15", { + m <- lm(Sepal.Width ~ Species / Petal.Length + Petal.Length, data = iris) + expect_identical( + unname(format_parameters(m)), + c( + "(Intercept)", + "Species [versicolor]", + "Species [virginica]", + "Petal Length", + "Species [versicolor] * Petal Length", + "Species [virginica] * Petal Length" ) - }) - - test_that("format_model_parameters-16", { - m <- lm(Sepal.Width ~ Species * Petal.Length + Petal.Length + Species, data = iris) - expect_identical( - unname(format_parameters(m)), - c( - "(Intercept)", "Species [versicolor]", "Species [virginica]", - "Petal Length", "Species [versicolor] * Petal Length", "Species [virginica] * Petal Length" - ) + ) + }) + + test_that("format_model_parameters-16", { + m <- lm(Sepal.Width ~ Species * Petal.Length + Petal.Length + Species, data = iris) + expect_identical( + unname(format_parameters(m)), + c( + "(Intercept)", + "Species [versicolor]", + "Species [virginica]", + "Petal Length", + "Species [versicolor] * Petal Length", + "Species [virginica] * Petal Length" ) - }) - - test_that("format_model_parameters-17", { - m <- lm(Sepal.Width ~ Species:Petal.Length + Petal.Length + Species, data = iris) - expect_identical( - unname(format_parameters(m)), - c( - "(Intercept)", "Petal Length", "Species [versicolor]", "Species [virginica]", - "Species [versicolor] * Petal Length", "Species [virginica] * Petal Length" - ) + ) + }) + + test_that("format_model_parameters-17", { + m <- lm(Sepal.Width ~ Species:Petal.Length + Petal.Length + Species, data = iris) + expect_identical( + unname(format_parameters(m)), + c( + "(Intercept)", + "Petal Length", + "Species [versicolor]", + "Species [virginica]", + "Species [versicolor] * Petal Length", + "Species [virginica] * Petal Length" ) - }) - - test_that("format_model_parameters-18", { - m <- lm(Sepal.Width ~ Species / Petal.Length + Petal.Length + Species, data = iris) - expect_identical( - unname(format_parameters(m)), - c( - "(Intercept)", "Species [versicolor]", "Species [virginica]", - "Petal Length", "Species [versicolor] * Petal Length", "Species [virginica] * Petal Length" - ) + ) + }) + + test_that("format_model_parameters-18", { + m <- lm(Sepal.Width ~ Species / Petal.Length + Petal.Length + Species, data = iris) + expect_identical( + unname(format_parameters(m)), + c( + "(Intercept)", + "Species [versicolor]", + "Species [virginica]", + "Petal Length", + "Species [versicolor] * Petal Length", + "Species [virginica] * Petal Length" ) - }) - } -) + ) + }) +}) + +test_that("format, format_parameters works with logicals", { + data(mtcars) + tmp <- mtcars + tmp$am <- as.logical(tmp$am) + tmp$cyl <- as.factor(tmp$cyl) + mod <- lm(mpg ~ am + cyl + disp, tmp) + expect_identical( + format_parameters(mod), + c( + `(Intercept)` = "(Intercept)", + amTRUE = "am [TRUE]", + cyl6 = "cyl [6]", + cyl8 = "cyl [8]", + disp = "disp" + ) + ) +}) + skip_if_not_installed("lme4") skip_if_not_installed("glmmTMB") @@ -194,11 +266,20 @@ test_that("format, compare_parameters, mixed models", { 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" + "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" ) ) }) diff --git a/tests/testthat/test-parameters_table.R b/tests/testthat/test-parameters_table.R index 9411fad62..d3ba8ec56 100644 --- a/tests/testthat/test-parameters_table.R +++ b/tests/testthat/test-parameters_table.R @@ -4,14 +4,22 @@ skip_if_not_installed("insight") test_that("parameters_table 1", { x <- model_parameters(lm(Sepal.Length ~ Species, data = iris), standardize = "refit") tab <- insight::format_table(x) - expect_equal(colnames(tab), c("Parameter", "Coefficient", "SE", "95% CI", "t(147)", "p")) + expect_equal( + colnames(tab), + c("Parameter", "Coefficient", "SE", "95% CI", "t(147)", "p") + ) }) test_that("parameters_table 2", { skip_if_not_installed("lme4") - x <- model_parameters(lme4::lmer(Sepal.Length ~ Petal.Length + (1 | Species), data = iris), effects = "fixed") + x <- model_parameters( + lme4::lmer(Sepal.Length ~ Petal.Length + (1 | Species), data = iris), + effects = "fixed" + ) tab <- insight::format_table(x) - expect_true(all(names(tab) == c("Parameter", "Coefficient", "SE", "95% CI", "t(146)", "p", "Effects"))) + expect_true(all( + names(tab) == c("Parameter", "Coefficient", "SE", "95% CI", "t(146)", "p", "Effects") + )) }) test_that("parameters_table 3", { diff --git a/tests/testthat/test-parameters_type.R b/tests/testthat/test-parameters_type.R index fdae089f7..2ff0bda83 100644 --- a/tests/testthat/test-parameters_type.R +++ b/tests/testthat/test-parameters_type.R @@ -13,5 +13,42 @@ test_that("parameters_type-1", { test_that("parameters_type-2", { model <- lm(Sepal.Length ~ Petal.Width * scale(Petal.Length, TRUE, FALSE), data = iris) - expect_equal(parameters_type(model)$Type, c("intercept", "numeric", "numeric", "interaction")) + expect_equal( + parameters_type(model)$Type, + c("intercept", "numeric", "numeric", "interaction") + ) +}) + + +test_that("parameters_type works with logicals", { + data(mtcars) + tmp <- mtcars + tmp$am <- as.logical(tmp$am) + tmp$cyl <- as.factor(tmp$cyl) + mod <- lm(mpg ~ am + cyl + disp, tmp) + expect_equal( + parameters_type(mod), + data.frame( + Parameter = c("(Intercept)", "amTRUE", "cyl6", "cyl8", "disp"), + Type = c("intercept", "logical", "factor", "factor", "numeric"), + Link = c("Mean", "Difference", "Difference", "Difference", "Association"), + Term = c("(Intercept)", "amTRUE", "cyl6", "cyl8", "disp"), + Variable = c(NA, "am", "cyl", "cyl", "disp"), + Level = c(NA, "TRUE", "6", "8", NA), + Secondary_Parameter = c( + NA_character_, + NA_character_, + NA_character_, + NA_character_, + NA_character_ + ), + Secondary_Type = c(NA, NA, NA, NA, NA), + Secondary_Link = c(NA, NA, NA, NA, NA), + Secondary_Term = c(NA, NA, NA, NA, NA), + Secondary_Variable = c(NA, NA, NA, NA, NA), + Secondary_Level = c(NA, NA, NA, NA, NA), + Tertiary_Parameter = c(NA, NA, NA, NA, NA) + ), + ignore_attr = TRUE + ) })