Skip to content

Commit

Permalink
add msg prefix
Browse files Browse the repository at this point in the history
  • Loading branch information
strengejacke committed Nov 21, 2024
1 parent 9066466 commit 6bf42f8
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 30 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Type: Package
Package: insight
Title: Easy Access to Model Information for Various Model Objects
Version: 0.99.0.18
Version: 0.99.0.19
Authors@R:
c(person(given = "Daniel",
family = "Lüdecke",
Expand Down
74 changes: 46 additions & 28 deletions R/find_formula.R
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
#'
#' @param action Should a message, warning or error be given for an invalid
#' formula? Must be one of `"message"`, `"warning"` (default) or `"error"`.
#' @param prefix_msg Optional string that will be added to the warning/error
#' message. This can be used to add additional information, e.g. about the
#' specific function that was calling `formula_ok()` and failed.
#' @param ... Currently not used.
#' @inheritParams find_predictors
#'
Expand Down Expand Up @@ -94,7 +97,12 @@ find_formula <- function(x, ...) {

#' @rdname find_formula
#' @export
formula_ok <- function(x, checks = "all", action = "warning", verbose = TRUE, ...) {
formula_ok <- function(x,
checks = "all",
action = "warning",
prefix_msg = NULL,
verbose = TRUE,
...) {
# if a model, retrieve formula. else, treat x as formula
if (is_model(x)) {
f <- find_formula(x, verbose = FALSE)
Expand Down Expand Up @@ -125,25 +133,25 @@ formula_ok <- function(x, checks = "all", action = "warning", verbose = TRUE, ..
# check if formula contains data name with "$". This may
# result in unexpected behaviour, and we should warn users
if (all(checks == "all") || "dollar" %in% checks) {
check_1 <- .check_formula_for_dollar(f, action = action, verbose = verbose)
check_1 <- .check_formula_for_dollar(f, action, prefix_msg, verbose = verbose)
}

# check if formula contains poly-term with "raw=T". In this case,
# all.vars() returns "T" as variable, which is not intended
if (all(checks == "all") || "T" %in% checks) {
check_2 <- .check_formula_for_T(f, action = action, verbose = verbose)
check_2 <- .check_formula_for_T(f, action, prefix_msg, verbose = verbose)
}

# check if formula contains index data frames as response variable
# this may result in unexpected behaviour, and we should warn users
if (all(checks == "all") || "index" %in% checks) {
check_3 <- .check_formula_index_df(f, x, action = action, verbose = verbose)
check_3 <- .check_formula_index_df(f, x, action, prefix_msg, verbose = verbose)
}

# check if formula contains non-syntactic variable names and uses backticks
# this may result in unexpected behaviour, and we should warn users
if (all(checks == "all") || "name" %in% checks) {
check_4 <- .check_formula_backticks(f, action = action, verbose = verbose)
check_4 <- .check_formula_backticks(f, action, prefix_msg, verbose = verbose)
}

all(check_1 && check_2 && check_3 && check_4)
Expand Down Expand Up @@ -1920,7 +1928,7 @@ find_formula.model_fit <- function(x, verbose = TRUE, ...) {
}


.check_formula_for_T <- function(f, action = "warning", verbose = TRUE) {
.check_formula_for_T <- function(f, action = "warning", prefix_msg = NULL, verbose = TRUE) {
f <- safe_deparse(f[[1]])

if (is_empty_object(f)) {
Expand All @@ -1929,11 +1937,12 @@ find_formula.model_fit <- function(x, verbose = TRUE, ...) {

if (grepl("(.*)poly\\((.*),\\s*raw\\s*=\\s*T\\)", f)) {
if (verbose) {
format_alert(
msg <- c(
prefix_msg,
"Looks like you are using `poly()` with \"raw = T\". This results in unexpected behaviour, because `all.vars()` considers `T` as variable.", # nolint
"Please use \"raw = TRUE\".",
type = action
"Please use \"raw = TRUE\"."
)
format_alert(msg, type = action)
}
return(FALSE)
}
Expand All @@ -1945,7 +1954,7 @@ find_formula.model_fit <- function(x, verbose = TRUE, ...) {
# in various functions throughout the easystats packages. We warn the user
# here...

.check_formula_for_dollar <- function(f, action = "warning", verbose = TRUE) {
.check_formula_for_dollar <- function(f, action = "warning", prefix_msg = NULL, verbose = TRUE) {
if (is_empty_object(f)) {
return(TRUE)
}
Expand All @@ -1956,10 +1965,14 @@ find_formula.model_fit <- function(x, verbose = TRUE, ...) {
format_error(attributes(fc)$condition$message)
}
if (verbose) {
format_alert(paste0(
"Using `$` in model formulas can produce unexpected results. Specify your model using the `data` argument instead.", # nolint
"\n Try: ", fc$formula, ", data = ", fc$data
), type = action)
msg <- c(
prefix_msg,
paste0(
"Using `$` in model formulas can produce unexpected results. Specify your model using the `data` argument instead.", # nolint
"\n Try: ", fc$formula, ", data = ", fc$data
)
)
format_alert(msg, type = action)
}
return(FALSE)
}
Expand All @@ -1971,17 +1984,18 @@ find_formula.model_fit <- function(x, verbose = TRUE, ...) {
# cause problems in various functions throughout the easystats packages. We
# warn the user here...

.check_formula_index_df <- function(f, x, action = "warning", verbose = TRUE) {
.check_formula_index_df <- function(f, x, action = "warning", prefix_msg = NULL, verbose = TRUE) {
if (is_empty_object(f)) {
return(TRUE)
}
resp <- .safe(safe_deparse(f$conditional[[2]]))
if (!is.null(resp) && any(grepl("\\b\\w+\\[.*?,.*?\\]", resp))) {
if (verbose) {
format_alert(
"Using indexed data frames, such as `df[, 5]`, as model response can produce unexpected results. Specify your model using the literal name of the response variable instead.", # nolint
type = action
msg <- c(
prefix_msg,
"Using indexed data frames, such as `df[, 5]`, as model response can produce unexpected results. Specify your model using the literal name of the response variable instead." # nolint
)
format_alert(msg, type = action)
}
return(FALSE)
}
Expand All @@ -1992,23 +2006,27 @@ find_formula.model_fit <- function(x, verbose = TRUE, ...) {
# formulas with non-syntactic names, where backticks are used, may cause
# problems. warn user here

.check_formula_backticks <- function(f, action = "warning", verbose = TRUE) {
.check_formula_backticks <- function(f, action = "warning", prefix_msg = NULL, verbose = TRUE) {
if (is_empty_object(f)) {
return(TRUE)
}
resp <- .safe(safe_deparse(f$conditional))
if (!is.null(resp) && any(grepl("`", resp, fixed = TRUE))) {
if (verbose) {
bad_name <- gsub("(.*)`(.*)`(.*)", "\\2", resp)
format_alert(paste0(
"Looks like you are using syntactically invalid variables names, quoted in backticks: `",
bad_name,
"`. This may result in unexpected behaviour. Please rename your variables (e.g., `",
make.names(bad_name),
"` instead of `",
bad_name,
"`) and fit the model again." # nolint
), type = action)
msg <- c(
prefix_msg,
paste0(
"Looks like you are using syntactically invalid variables names, quoted in backticks: `",
bad_name,
"`. This may result in unexpected behaviour. Please rename your variables (e.g., `",
make.names(bad_name),
"` instead of `",
bad_name,
"`) and fit the model again."
)
)
format_alert(msg, type = action)
}
return(FALSE)
}
Expand Down
13 changes: 12 additions & 1 deletion man/find_formula.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions tests/testthat/test-find_formula.R
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,8 @@ test_that("formula warns when using backticks", {
# message types
expect_message(expect_false(formula_ok(m, action = "message")), regex = "syntactically")
expect_error(expect_false(formula_ok(m, action = "error")), regex = "syntactically")
# add own message
expect_message(expect_false(
formula_ok(m, action = "message", prefix_msg = "Test-Unit failed.")
), regex = "Test-Unit failed")
})

0 comments on commit 6bf42f8

Please sign in to comment.