Skip to content

Commit 00cd2c2

Browse files
Add condense_control() function (#808)
* add condense_control function * add tests for condense_control * use condense_control function * update news about condense_control * correct spacing * add missing updated test * add reminder to add arguments to other control functions
1 parent c24b014 commit 00cd2c2

File tree

10 files changed

+119
-8
lines changed

10 files changed

+119
-8
lines changed

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ export(check_empty_ellipse)
155155
export(check_final_param)
156156
export(check_model_doesnt_exist)
157157
export(check_model_exists)
158+
export(condense_control)
158159
export(contr_one_hot)
159160
export(control_parsnip)
160161
export(convert_stan_interval)

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
* `fit_xy()` now fails when the model mode is unknown.
66

7+
* `fit()` and `fit_xy()` doesn't error anymore if `control` argument isn't a `control_parsnip()` object. Will work as long as the object passed to `control` includes the same elements as `control_parsnip()`.
8+
79
# parsnip 1.0.1
810

911
* Enabled passing additional engine arguments with the xgboost `boost_tree()` engine. To supply engine-specific arguments that are documented in `xgboost::xgb.train()` as arguments to be passed via `params`, supply the list elements directly as named arguments to `set_engine()`. Read more in `?details_boost_tree_xgboost` (#787).

R/condense_control.R

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#' Condense control object into strictly smaller control object
2+
#'
3+
#' This function is used to help the hierarchy of control functions used
4+
#' throughout the tidymodels packages. It is now assumed that each control
5+
#' function is either a subset or a superset of another control function.
6+
#'
7+
#' @param x A control object to be condensed.
8+
#' @param ref A control object that is used to determine what element should be
9+
#' kept.
10+
#'
11+
#' @return A control object with the same elements and classes of `ref`, with
12+
#' values of `x`.
13+
#' @keywords internal
14+
#' @export
15+
#'
16+
#' @examples
17+
#' ctrl <- control_parsnip(catch = TRUE)
18+
#' ctrl$allow_par <- TRUE
19+
#' str(ctrl)
20+
#'
21+
#' ctrl <- condense_control(ctrl, control_parsnip())
22+
#' str(ctrl)
23+
condense_control <- function(x, ref) {
24+
mismatch <- setdiff(names(ref), names(x))
25+
if (length(mismatch)) {
26+
rlang::abort(
27+
c(
28+
glue::glue(
29+
"Object of class `{class(x)[1]}` cannot be corresed to ",
30+
"object of class `{class(ref)[1]}`."
31+
),
32+
"The following arguments are missing:",
33+
glue::glue_collapse(
34+
glue::single_quote(mismatch),
35+
sep = ", ", last = ", and "
36+
)
37+
)
38+
)
39+
}
40+
res <- x[names(ref)]
41+
class(res) <- class(ref)
42+
res
43+
}

R/control_parsnip.R

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#'
2121
#' @export
2222
control_parsnip <- function(verbosity = 1L, catch = FALSE) {
23+
# Any added arguments should also be added in superset control functions
24+
# in other packages
2325
res <- list(verbosity = verbosity, catch = catch)
2426
res <- check_control(res)
2527
class(res) <- "control_parsnip"

R/fit.R

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,7 @@ fit.model_spec <-
112112
if (object$mode == "unknown") {
113113
rlang::abort("Please set the mode in the model specification.")
114114
}
115-
if (!identical(class(control), class(control_parsnip()))) {
116-
rlang::abort("The 'control' argument should have class 'control_parsnip'.")
117-
}
115+
control <- condense_control(control, control_parsnip())
118116
check_case_weights(case_weights, object)
119117

120118
dots <- quos(...)
@@ -238,9 +236,8 @@ fit_xy.model_spec <-
238236
rlang::abort("Survival models must use the formula interface.")
239237
}
240238

241-
if (!identical(class(control), class(control_parsnip()))) {
242-
rlang::abort("The 'control' argument should have class 'control_parsnip'.")
243-
}
239+
control <- condense_control(control, control_parsnip())
240+
244241
if (is.null(colnames(x))) {
245242
rlang::abort("'x' should have column names.")
246243
}

_pkgdown.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ reference:
9494

9595
- title: Developer tools
9696
contents:
97+
- condense_control
9798
- contr_one_hot
9899
- set_new_model
99100
- maybe_matrix

man/condense_control.Rd

Lines changed: 32 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# condense_control works
2+
3+
Code
4+
condense_control(control_parsnip(), ctrl)
5+
Condition
6+
Error in `condense_control()`:
7+
! Object of class `control_parsnip` cannot be corresed to object of class `control_parsnip`.
8+
* The following arguments are missing:
9+
* 'allow_par', and 'anotherone'
10+
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
test_that("condense_control works", {
2+
ctrl <- control_parsnip()
3+
4+
expect_equal(
5+
condense_control(ctrl, ctrl),
6+
ctrl
7+
)
8+
9+
ctrl$allow_par <- TRUE
10+
ctrl$catch <- TRUE
11+
12+
expect_equal(
13+
condense_control(ctrl, control_parsnip()),
14+
control_parsnip(catch = TRUE)
15+
)
16+
17+
ctrl$anotherone <- 2
18+
expect_snapshot(error = TRUE,
19+
condense_control(control_parsnip(), ctrl)
20+
)
21+
})

tests/testthat/test_misc.R

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,15 @@ test_that('control class', {
7676
x <- linear_reg() %>% set_engine("lm")
7777
ctrl <- control_parsnip()
7878
class(ctrl) <- c("potato", "chair")
79+
# This doesn't error anymore because `condense_control()` doesn't care about
80+
# classes, it cares about elements
7981
expect_error(
8082
fit(x, mpg ~ ., data = mtcars, control = ctrl),
81-
"The 'control' argument should have class 'control_parsnip'"
83+
NA
8284
)
8385
expect_error(
8486
fit_xy(x, x = mtcars[, -1], y = mtcars$mpg, control = ctrl),
85-
"The 'control' argument should have class 'control_parsnip'"
87+
NA
8688
)
8789
})
8890

0 commit comments

Comments
 (0)