From 19ddd2f8cafe7ef1b45aaf674d5397ff9f2a9758 Mon Sep 17 00:00:00 2001 From: Daniel Date: Sun, 12 Mar 2023 18:41:43 +0100 Subject: [PATCH 1/5] find_ and get_ methods with models of multiple formula components like clm() & lme() Fixes #727 --- NAMESPACE | 1 + R/find_weights.R | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/NAMESPACE b/NAMESPACE index 8ad9a226e..74e0c03de 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -323,6 +323,7 @@ S3method(find_terms,default) S3method(find_terms,mipo) S3method(find_weights,brmsfit) S3method(find_weights,default) +S3method(find_weights,lme) S3method(find_weights,merMod) S3method(find_weights,model_fit) S3method(format,insight_formula) diff --git a/R/find_weights.R b/R/find_weights.R index 15c26dd29..8804de8ca 100644 --- a/R/find_weights.R +++ b/R/find_weights.R @@ -96,3 +96,9 @@ find_weights.merMod <- function(x, ...) { } ) } + + +#' @export +find_weights.lme <- function(x, ...) { + w <- find_weights.default(x, ...) +} From 84d386e5810e5243b6b868cb1dcf5ae1f068ded2 Mon Sep 17 00:00:00 2001 From: Daniel Date: Sun, 12 Mar 2023 18:55:11 +0100 Subject: [PATCH 2/5] fix lme issue --- R/find_weights.R | 12 ++++++++++ tests/testthat/test-find_weights.R | 36 ++++++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/R/find_weights.R b/R/find_weights.R index 8804de8ca..45e668e0c 100644 --- a/R/find_weights.R +++ b/R/find_weights.R @@ -101,4 +101,16 @@ find_weights.merMod <- function(x, ...) { #' @export find_weights.lme <- function(x, ...) { w <- find_weights.default(x, ...) + # any weights? If so, get formula + if (!is.null(w)) { + # in lme(), weights are either an optional varFunc object or a one-sided + # formula. The formula is usally stored in "$modelStruct$varStruct" + w_formula <- .safe(stats::formula(x$modelStruct$varStruct)) + if (!is.null(w_formula)) { + w <- all.vars(w_formula) + } else { + w <- NULL + } + } + w } diff --git a/tests/testthat/test-find_weights.R b/tests/testthat/test-find_weights.R index 4f68a3aa1..95dc5f054 100644 --- a/tests/testthat/test-find_weights.R +++ b/tests/testthat/test-find_weights.R @@ -3,12 +3,44 @@ if (skip_if_not_or_load_if_installed("lme4")) { data(mtcars) mtcars$weight <- rnorm(nrow(mtcars), 1, 0.3) m <- lm(mpg ~ wt + cyl + vs, data = mtcars, weights = weight) - expect_equal(find_weights(m), "weight") + expect_identical(find_weights(m), "weight") }) test_that("find_weights", { data(iris) iris$wgt <- rnorm(nrow(iris), 1, 0.3) m <- lmer(Sepal.Width ~ Sepal.Length + (1 | Species), data = iris, weights = wgt) - expect_equal(find_weights(m), "wgt") + expect_identical(find_weights(m), "wgt") + }) +} + + +if (skip_if_not_or_load_if_installed("nlme")) { + data(Orthodont) + Orthodont$w <- abs(rnorm(nrow(Orthodont))) + + m1 <- lme( + distance ~ age, + data = Orthodont, + random = ~ 1 | Subject, + weights = varIdent(form = ~ 1 | Sex) + ) + + m2 <- lme( + distance ~ age, + data = Orthodont, + random = ~ 1 | Subject + ) + + m3 <- lme( + distance ~ age, + data = Orthodont, + random = ~ 1 | Subject, + weights = ~w + ) + + test_that("find_weights", { + expect_identical(find_weights(m1), "Sex") + expect_null(find_weights(m2)) + expect_identical(find_weights(m3), "w") }) } From 46abc888b75bb0e314df4fb0a07affef71ec8577 Mon Sep 17 00:00:00 2001 From: Daniel Date: Sun, 12 Mar 2023 18:55:56 +0100 Subject: [PATCH 3/5] news, version --- DESCRIPTION | 2 +- NEWS.md | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 32e429b29..aa114d785 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Type: Package Package: insight Title: Easy Access to Model Information for Various Model Objects -Version: 0.19.0.9 +Version: 0.19.0.10 Authors@R: c(person(given = "Daniel", family = "Lüdecke", diff --git a/NEWS.md b/NEWS.md index 5a7bba6e6..e32b347b4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -19,6 +19,8 @@ * Fixed issue in `get_data()` for results from `kruskal.test()`. +* Fixed issue in `find_weights()` for models of class `lme`. + # insight 0.19.0 ## New supported models From 5331a48784796767189bd3868cde2d81a921bbce Mon Sep 17 00:00:00 2001 From: Daniel Date: Sun, 12 Mar 2023 19:13:03 +0100 Subject: [PATCH 4/5] fix for clm --- NAMESPACE | 1 + NEWS.md | 4 +++ R/find_formula.R | 11 +++++++ R/helper_functions.R | 3 +- tests/testthat/test-clm.R | 65 ++++++++++++++++++++++++++++++--------- 5 files changed, 69 insertions(+), 15 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 74e0c03de..eaff73205 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -100,6 +100,7 @@ S3method(find_formula,btergm) S3method(find_formula,censReg) S3method(find_formula,cgamm) S3method(find_formula,cglm) +S3method(find_formula,clm) S3method(find_formula,clm2) S3method(find_formula,clmm) S3method(find_formula,clmm2) diff --git a/NEWS.md b/NEWS.md index e32b347b4..5598e5378 100644 --- a/NEWS.md +++ b/NEWS.md @@ -15,6 +15,10 @@ * `format_table()` now also formats columns named `SGPV` (second generation p-values) as p-values. +* Functions for models of class `clm` (like `find_formula()`, `find_variables()`, + `get_data()` etc.) now also include variables that were defined as `scale` or + `nominal` component. + ## Bug fixes * Fixed issue in `get_data()` for results from `kruskal.test()`. diff --git a/R/find_formula.R b/R/find_formula.R index 1f599862e..225f4e379 100644 --- a/R/find_formula.R +++ b/R/find_formula.R @@ -1037,6 +1037,17 @@ find_formula.clm2 <- function(x, verbose = TRUE, ...) { } +#' @export +find_formula.clm <- function(x, verbose = TRUE, ...) { + f <- compact_list(list( + conditional = stats::formula(x), + scale = x$formulas$scale, + nominal = x$formulas$nominal + )) + .find_formula_return(f, verbose = verbose) +} + + #' @export find_formula.DirichletRegModel <- function(x, verbose = TRUE, ...) { f <- safe_deparse(stats::formula(x)) diff --git a/R/helper_functions.R b/R/helper_functions.R index 70741dfea..a8e12cb56 100644 --- a/R/helper_functions.R +++ b/R/helper_functions.R @@ -208,7 +208,8 @@ "sigma", "nu", "tau", "correlation", "slopes", "cluster", "extra", "scale", "marginal", "alpha", "beta", "survival", "infrequent_purchase", "auxiliary", "mix", "shiftprop", "phi", "ndt", "hu", "xi", "coi", "zoi", "aux", "dist", - "selection", "outcome", "time_dummies", "sigma_random", "beta_random", "car" + "selection", "outcome", "time_dummies", "sigma_random", "beta_random", "car", + "nominal" ) } diff --git a/tests/testthat/test-clm.R b/tests/testthat/test-clm.R index f50a7ba99..a76d052ef 100644 --- a/tests/testthat/test-clm.R +++ b/tests/testthat/test-clm.R @@ -2,6 +2,13 @@ if (skip_if_not_or_load_if_installed("ordinal")) { data(wine, package = "ordinal") m1 <- clm(rating ~ temp * contact, data = wine) + data(mtcars) + m2 <- suppressWarnings(clm( # nominal + scale effects + cyl ~ wt, + scale = ~vs, nominal = ~hp, + data = transform(mtcars, cyl = factor(cyl)) + )) + test_that("model_info", { expect_true(model_info(m1)$is_ordinal) expect_false(model_info(m1)$is_multinomial) @@ -12,6 +19,10 @@ if (skip_if_not_or_load_if_installed("ordinal")) { expect_identical(find_predictors(m1), list(conditional = c("temp", "contact"))) expect_identical(find_predictors(m1, flatten = TRUE), c("temp", "contact")) expect_null(find_predictors(m1, effects = "random")) + expect_identical( + find_predictors(m2), + list(conditional = "wt", scale = "vs", nominal = "hp") + ) }) test_that("find_random", { @@ -27,11 +38,11 @@ if (skip_if_not_or_load_if_installed("ordinal")) { }) test_that("get_response", { - expect_equal(get_response(m1), wine$rating) + expect_equal(get_response(m1), wine$rating, tolerance = 1e-5) }) test_that("get_predictors", { - expect_equal(colnames(get_predictors(m1)), c("temp", "contact")) + expect_identical(colnames(get_predictors(m1)), c("temp", "contact")) }) test_that("link_inverse", { @@ -39,8 +50,9 @@ if (skip_if_not_or_load_if_installed("ordinal")) { }) test_that("get_data", { - expect_equal(nrow(get_data(m1)), 72) - expect_equal(colnames(get_data(m1)), c("rating", "temp", "contact")) + expect_identical(nrow(get_data(m1)), 72L) + expect_identical(colnames(get_data(m1)), c("rating", "temp", "contact")) + expect_identical(colnames(get_data(m2)), c("cyl", "wt", "vs", "hp")) }) test_that("find_formula", { @@ -50,21 +62,45 @@ if (skip_if_not_or_load_if_installed("ordinal")) { list(conditional = as.formula("rating ~ temp * contact")), ignore_attr = TRUE ) + expect_equal( + find_formula(m2), + list( + conditional = as.formula("cyl ~ wt"), + scale = as.formula("~vs"), + nominal = as.formula("~hp") + ), + ignore_attr = TRUE + ) + }) + + test_that("find_variables", { + expect_identical( + find_variables(m2), + list(response = "cyl", conditional = "wt", scale = "vs", nominal = "hp") + ) }) test_that("find_terms", { - expect_equal(find_terms(m1), list( - response = "rating", - conditional = c("temp", "contact") - )) expect_equal( + find_terms(m1), + list( + response = "rating", + conditional = c("temp", "contact") + ), + ignore_attr = TRUE + ) + expect_identical( find_terms(m1, flatten = TRUE), c("rating", "temp", "contact") ) + expect_identical( + find_terms(m2), + list(response = "cyl", conditional = "wt", scale = "vs", nominal = "hp") + ) }) test_that("n_obs", { - expect_equal(n_obs(m1), 72) + expect_identical(n_obs(m1), 72L) }) test_that("linkfun", { @@ -84,10 +120,11 @@ if (skip_if_not_or_load_if_installed("ordinal")) { "contactyes", "tempwarm:contactyes" ) - ) + ), + ignore_attr = TRUE ) - expect_equal(nrow(get_parameters(m1)), 7) - expect_equal( + expect_identical(nrow(get_parameters(m1)), 7L) + expect_identical( get_parameters(m1)$Parameter, c( "1|2", @@ -116,7 +153,7 @@ if (skip_if_not_or_load_if_installed("ordinal")) { y <- as.data.frame(get_predicted(m1, predict = NULL, type = "prob")) z <- predict(m1, type = "prob", newdata = nd, se.fit = TRUE) expect_true(all(c("Row", "Response", "Predicted", "SE") %in% colnames(x))) - expect_equal(x, y) + expect_equal(x, y, tolerance = 1e-5) for (i in 1:5) { expect_equal(x$Predicted[x$Response == i], unname(z$fit[, i]), ignore_attr = FALSE) expect_equal(x$SE[x$Response == i], unname(z$se.fit[, i]), ignore_attr = FALSE) @@ -124,7 +161,7 @@ if (skip_if_not_or_load_if_installed("ordinal")) { x <- as.data.frame(get_predicted(m1, predict = "classification")) y <- as.data.frame(get_predicted(m1, predict = NULL, type = "class")) z <- predict(m1, type = "class", newdata = nd) - expect_equal(x, y) + expect_equal(x, y, tolerance = 1e-5) expect_equal(as.character(x$Predicted), as.character(z$fit), ignore_attr = FALSE) # we use a hack to handle in-formula factors From e30009b58be26a0e66b24491e0c43683458f76a9 Mon Sep 17 00:00:00 2001 From: Daniel Date: Sun, 12 Mar 2023 19:35:49 +0100 Subject: [PATCH 5/5] fix test --- tests/testthat/test-clm.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testthat/test-clm.R b/tests/testthat/test-clm.R index a76d052ef..5fb193e6c 100644 --- a/tests/testthat/test-clm.R +++ b/tests/testthat/test-clm.R @@ -100,7 +100,7 @@ if (skip_if_not_or_load_if_installed("ordinal")) { }) test_that("n_obs", { - expect_identical(n_obs(m1), 72L) + expect_equal(n_obs(m1), 72) # nolint }) test_that("linkfun", {