Skip to content

Commit 28b5449

Browse files
authored
varying_args() improvements: (#137)
- Update documentation for varying_args() - For recipes, using the unique step id as the id column - For model_specs, using the top level class as the id column - Better return value for recipes with no steps (tibble with correct column names)
1 parent 74d36ad commit 28b5449

File tree

3 files changed

+181
-155
lines changed

3 files changed

+181
-155
lines changed

R/varying.R

Lines changed: 73 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -2,75 +2,81 @@
22
#'
33
#' [varying()] is used when a parameter will be specified at a later date.
44
#' @export
5-
varying <- function()
5+
varying <- function() {
66
quote(varying())
7+
}
78

89
#' Determine varying arguments
910
#'
10-
#' `varying_args` takes a model specification and lists all of the arguments
11-
#' along with whether they are fully specified or not.
12-
#' @param x An object
13-
#' @param id A string describing the object `x`.
11+
#' `varying_args()` takes a model specification or a recipe and returns a tibble
12+
#' of information on all possible varying arguments and whether or not they
13+
#' are actually varying.
14+
#'
15+
#' The `id` column is determined differently depending on whether a `model_spec`
16+
#' or a `recipe` is used. For a `model_spec`, the first class is used. For
17+
#' a `recipe`, the unique step `id` is used.
18+
#'
19+
#' @param x A `model_spec` or a `recipe`.
20+
#'
1421
#' @param ... Not currently used.
15-
#' @return A tibble with columns for the parameter name (`name`), whether is
16-
#' contains _any_ varying value (`varying`), the `id` for the object, and the
17-
#' class that was used to call the method (`type`).
22+
#'
23+
#' @return A tibble with columns for the parameter name (`name`), whether it
24+
#' contains _any_ varying value (`varying`), the `id` for the object, and the
25+
#' class that was used to call the method (`type`).
26+
#'
1827
#' @examples
19-
#' library(dplyr)
20-
#' library(rlang)
2128
#'
22-
#' rand_forest() %>% varying_args(id = "plain")
29+
#' # List all possible varying args for the random forest spec
30+
#' rand_forest() %>% varying_args()
2331
#'
24-
#' rand_forest(mtry = varying()) %>% varying_args(id = "one arg")
32+
#' # mtry is now recognized as varying
33+
#' rand_forest(mtry = varying()) %>% varying_args()
2534
#'
35+
#' # Even engine specific arguments can vary
2636
#' rand_forest() %>%
2737
#' set_engine("ranger", sample.fraction = varying()) %>%
28-
#' varying_args(id = "only eng_args")
38+
#' varying_args()
2939
#'
3040
#' rand_forest() %>%
3141
#' set_engine(
32-
#' "ranger",
33-
#' strata = expr(Class),
34-
#' sampsize = c(varying(), varying())
42+
#' "randomForest",
43+
#' strata = Class,
44+
#' sampsize = varying()
3545
#' ) %>%
36-
#' varying_args(id = "add an expr")
37-
#'
38-
#' rand_forest() %>%
39-
#' set_engine("ranger", classwt = c(class1 = 1, class2 = varying())) %>%
40-
#' varying_args(id = "list of values")
46+
#' varying_args()
4147
#'
4248
#' @export
43-
varying_args <- function (x, id, ...)
49+
varying_args <- function (x, ...) {
4450
UseMethod("varying_args")
51+
}
4552

4653
#' @importFrom purrr map map_lgl
4754
#' @export
4855
#' @export varying_args.model_spec
4956
#' @rdname varying_args
50-
varying_args.model_spec <- function(x, id = NULL, ...) {
51-
cl <- match.call()
57+
varying_args.model_spec <- function(x, ...) {
5258

53-
if (!is.null(id) && !is.character(id))
54-
stop ("`id` should be a single character string.", call. = FALSE)
55-
id <- id[1]
59+
# use the model_spec top level class as the id
60+
id <- class(x)[1]
61+
62+
if (length(x$args) == 0L & length(x$eng_args) == 0L) {
63+
return(varying_tbl())
64+
}
5665

57-
if (is.null(id))
58-
id <- deparse(cl$x)
66+
# Locate varying args in spec args and engine specific args
5967
varying_args <- map_lgl(x$args, find_varying)
6068
varying_eng_args <- map_lgl(x$eng_args, find_varying)
69+
6170
res <- c(varying_args, varying_eng_args)
62-
tibble(
71+
72+
varying_tbl(
6373
name = names(res),
6474
varying = unname(res),
6575
id = id,
66-
type = caller_method(cl)
76+
type = "model_spec"
6777
)
68-
}
6978

70-
# NOTE Look at the `sampsize` and `classwt` examples above. Using varying() in
71-
# a vector will convert it to list. When the model-specific `translate` is
72-
# run, we should catch those and convert them back to vectors if the varying
73-
# parameter has been replaced with a real value.
79+
}
7480

7581
# Need to figure out a way to meld the results of varying_args with
7682
# parameter objects from `dials` or from novel parameters in the user's
@@ -81,36 +87,29 @@ varying_args.model_spec <- function(x, id = NULL, ...) {
8187
# Maybe use this data as substrate to make a new object type (param_set?) that
8288
# would have its own methods for grids and random sampling.
8389

84-
# lots of code duplication below and probably poor planning; just a prototype.
85-
# once the generics package is done, these will go into recipes
86-
8790
#' @importFrom purrr map2_dfr map_chr
8891
#' @export
8992
#' @export varying_args.recipe
9093
#' @rdname varying_args
91-
varying_args.recipe <- function(x, id = NULL, ...) {
92-
step_type <- map_chr(x$steps, function(x) class(x)[1])
93-
step_type <- make.names(step_type, unique = TRUE) # change with new tibble version
94-
res <- map2_dfr(x$steps, step_type, varying_args)
95-
res
94+
varying_args.recipe <- function(x, ...) {
95+
96+
steps <- x$steps
97+
98+
if (length(steps) == 0L) {
99+
return(varying_tbl())
100+
}
101+
102+
map_dfr(x$steps, varying_args)
96103
}
97104

98105
#' @importFrom purrr map map_lgl
99106
#' @export
100107
#' @export varying_args.step
101108
#' @rdname varying_args
102-
varying_args.step <- function(x, id = NULL, ...) {
103-
cl <- match.call()
109+
varying_args.step <- function(x, ...) {
104110

105-
if (!is.null(id) && !is.character(id)) {
106-
stop ("`id` should be a single character string.", call. = FALSE)
107-
}
108-
109-
id <- id[1]
110-
111-
if (is.null(id)) {
112-
id <- deparse(cl$x)
113-
}
111+
# Unique step id
112+
id <- x$id
114113

115114
# Grab the step class before the subset, as that removes the class
116115
step_type <- class(x)[1]
@@ -127,12 +126,29 @@ varying_args.step <- function(x, id = NULL, ...) {
127126
# remove the non-varying arguments as they are not important
128127
res <- res[!(names(x) %in% non_varying_step_arguments)]
129128

130-
tibble(
129+
varying_tbl(
131130
name = names(res),
132131
varying = unname(res),
133132
id = id,
134-
type = caller_method(cl)
133+
type = "step"
134+
)
135+
136+
}
137+
138+
# useful for standardization and for creating a 0 row varying tbl
139+
# (i.e. for when there are no steps in a recipe)
140+
varying_tbl <- function(name = character(),
141+
varying = logical(),
142+
id = character(),
143+
type = character()) {
144+
145+
tibble(
146+
name = name,
147+
varying = varying,
148+
id = id,
149+
type = type
135150
)
151+
136152
}
137153

138154
validate_only_allowed_step_args <- function(x, step_type) {
@@ -214,11 +230,3 @@ find_varying <- function(x) {
214230

215231
return(any_varying_elems)
216232
}
217-
218-
caller_method <- function(cl) {
219-
x <- cl[[1]]
220-
x <- deparse(x)
221-
x <- gsub("varying_args.", "", x, fixed = TRUE)
222-
x
223-
}
224-

man/varying_args.Rd

Lines changed: 24 additions & 23 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)