diff --git a/DESCRIPTION b/DESCRIPTION index 9d18cc9dc..5d377f6c2 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -111,7 +111,8 @@ Imports: rlang (>= 0.2.0), storr (>= 1.1.0), txtq (>= 0.1.3), - utils + utils, + vctrs (>= 0.2.0) Suggests: abind, bindr, diff --git a/NAMESPACE b/NAMESPACE index 7ed4d6acd..bb5ee5f0d 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -250,4 +250,6 @@ importFrom(utils,stack) importFrom(utils,type.convert) importFrom(utils,unzip) importFrom(utils,write.table) +importFrom(vctrs,vec_c) +importFrom(vctrs,vec_slice) useDynLib(drake, .registration = TRUE) diff --git a/NEWS.md b/NEWS.md index 91aa9da48..75c5416b2 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,9 @@ # Version 7.8.0.9000 +## Breaking changes + +- Embrace the `vctrs` paradigm and its type stability for dynamic branching (#1105, #1106). + ## New features - Add a new `log_build_times` argument to `make()` and `drake_config()`. Allows users to disable the recording of build times. Produces a speedup of up to 20% on Macs (#1078). diff --git a/R/cache.R b/R/cache.R index 2f5cadddb..fa1fa49ef 100644 --- a/R/cache.R +++ b/R/cache.R @@ -323,7 +323,8 @@ get_subtargets.drake_dynamic <- function(hashes, cache, subtargets) { if (!is.null(subtargets)) { hashes <- hashes[subtargets] } - lapply(hashes, cache$get_value, use_cache = FALSE) + out <- lapply(hashes, cache$get_value, use_cache = FALSE) + do.call(vec_c, out) } get_subtargets.default <- function(hashes, cache, subtargets) { diff --git a/R/drake_plan.R b/R/drake_plan.R index 7b17d588b..341cb0fba 100644 --- a/R/drake_plan.R +++ b/R/drake_plan.R @@ -253,18 +253,18 @@ #' drake_plan(x = target(f(char), transform = map(char = !!sms))) #' #' # Dynamic branching +#' # Get the mean mpg for each cyl in the mtcars dataset. #' plan <- drake_plan( -#' w = c("a", "a", "b", "b"), -#' x = seq_len(4), -#' y = target(x + 1, dynamic = map(x)), -#' z = target(list(y = y, w = w), dynamic = group(y, .by = w)) +#' raw = mtcars, +#' group_index = raw$cyl, +#' munged = target(raw[, c("mpg", "cyl")], dynamic = map(raw)), +#' mean_mpg_by_cyl = target( +#' data.frame(mpg = mean(munged$mpg), cyl = munged$cyl[1]), +#' dynamic = group(munged, .by = group_index) +#' ) #' ) #' make(plan) -#' subtargets(y) -#' readd(subtargets(y)[1], character_only = TRUE) -#' readd(subtargets(y)[2], character_only = TRUE) -#' readd(subtargets(z)[1], character_only = TRUE) -#' readd(subtargets(z)[2], character_only = TRUE) +#' readd(mean_mpg_by_cyl) #' }) #' } drake_plan <- function( diff --git a/R/drake_plan_helpers.R b/R/drake_plan_helpers.R index eeba3a8ff..8818d3420 100644 --- a/R/drake_plan_helpers.R +++ b/R/drake_plan_helpers.R @@ -525,9 +525,7 @@ no_deps <- function(x = NULL) { #' y = target(id_chr(), dynamic = map(x)) #' ) #' make(plan) -#' ys <- subtargets(y) -#' ys -#' readd(ys[1], character_only = TRUE) +#' readd(y, subtargets = 1) #' # Static branching #' plan <- drake_plan( #' y = target(c(x, .id_chr), transform = map(x = !!seq_len(4))) diff --git a/R/dynamic.R b/R/dynamic.R index df685c5c4..4cddcc6d5 100644 --- a/R/dynamic.R +++ b/R/dynamic.R @@ -13,14 +13,14 @@ #' w = c("a", "a", "b", "b"), #' x = seq_len(4), #' y = target(x + 1, dynamic = map(x)), -#' z = target(list(y = y, w = w), dynamic = group(y, .by = w)) +#' z = target(sum(x) + sum(y), dynamic = group(x, y, .by = w)) #' ) #' make(plan) #' subtargets(y) -#' readd(subtargets(y)[1], character_only = TRUE) -#' readd(subtargets(y)[2], character_only = TRUE) -#' readd(subtargets(z)[1], character_only = TRUE) -#' readd(subtargets(z)[2], character_only = TRUE) +#' subtargets(z) +#' readd(x) +#' readd(y) +#' readd(z) #' }) #' } subtargets <- function( @@ -69,7 +69,7 @@ subtargets <- function( #' #' # The first trace lets us see the values of w #' # that go with the sub-targets of y. -#' y = target(c(w, x), dynamic = cross(w, x, .trace = w)), +#' y = target(paste0(w, x), dynamic = cross(w, x, .trace = w)), #' #' # We can use the trace as a grouping variable for the next #' # group(). @@ -77,7 +77,10 @@ subtargets <- function( #' #' # Now, we use the trace again to keep track of the #' # values of w corresponding to the sub-targets of z. -#' z = target(y, dynamic = group(y, .by = w_tr, .trace = w_tr)) +#' z = target( +#' paste0(y, collapse = "-"), +#' dynamic = group(y, .by = w_tr, .trace = w_tr) +#' ) #' ) #' make(plan) #' @@ -88,7 +91,7 @@ subtargets <- function( #' read_trace("w", "y") #' #' # And we know which values of `w_tr` (and thus `w`) -#' # match up with the sub-targets of `z`. +#' # match up with the sub-targets of `y`. #' readd(z) #' read_trace("w_tr", "z") #' }) @@ -131,7 +134,7 @@ read_trace <- function( #' #' # The first trace lets us see the values of w #' # that go with the sub-targets of y. -#' y = target(c(w, x), dynamic = cross(w, x, .trace = w)), +#' y = target(paste0(w, x), dynamic = cross(w, x, .trace = w)), #' #' # We can use the trace as a grouping variable for the next #' # group(). @@ -139,12 +142,22 @@ read_trace <- function( #' #' # Now, we use the trace again to keep track of the #' # values of w corresponding to the sub-targets of z. -#' z = target(y, dynamic = group(y, .by = w_tr, .trace = w_tr)) +#' z = target( +#' paste0(y, collapse = "-"), +#' dynamic = group(y, .by = w_tr, .trace = w_tr) +#' ) #' ) #' make(plan) #' #' # We can read the trace outside make(). +#' # That way, we know which values of `w` correspond +#' # to the sub-targets of `y`. +#' readd(y) #' read_trace("w", "y") +#' +#' # And we know which values of `w_tr` (and thus `w`) +#' # match up with the sub-targets of `y`. +#' readd(z) #' read_trace("w_tr", "z") #' }) #' } @@ -412,36 +425,7 @@ as_dynamic <- function(x) { } dynamic_subvalue <- function(value, index) { - UseMethod("dynamic_subvalue") -} - -dynamic_subvalue.data.frame <- function(value, index) { - value[index,, drop = FALSE] # nolint -} - -dynamic_subvalue.drake_dynamic <- function(value, index) { - dynamic_subvalue_vector(value, index) -} - -dynamic_subvalue.default <- function(value, index) { - if (is.null(dim(value))) { - dynamic_subvalue_vector(value, index) - } else { - dynamic_subvalue_array(value, index) - } -} - -dynamic_subvalue_array <- function(value, index) { - ref <- slice.index(value, 1L) - out <- value[ref %in% index] - dim <- dim(value) - dim[1] <- length(index) - dim(out) <- dim - out -} - -dynamic_subvalue_vector <- function(value, index) { - value[index] + vec_slice(x = value, i = index) } match_dynamic_call <- function(dynamic) { diff --git a/R/make.R b/R/make.R index 8b977b968..d4cb0ffdb 100644 --- a/R/make.R +++ b/R/make.R @@ -109,18 +109,18 @@ #' clean() # Start from scratch next time around. #' } #' # Dynamic branching +#' # Get the mean mpg for each cyl in the mtcars dataset. #' plan <- drake_plan( -#' w = c("a", "a", "b", "b"), -#' x = seq_len(4), -#' y = target(x + 1, dynamic = map(x)), -#' z = target(list(y = y, w = w), dynamic = group(y, .by = w)) +#' raw = mtcars, +#' group_index = raw$cyl, +#' munged = target(raw[, c("mpg", "cyl")], dynamic = map(raw)), +#' mean_mpg_by_cyl = target( +#' data.frame(mpg = mean(munged$mpg), cyl = munged$cyl[1]), +#' dynamic = group(munged, .by = group_index) +#' ) #' ) #' make(plan) -#' subtargets(y) -#' readd(subtargets(y)[1], character_only = TRUE) -#' readd(subtargets(y)[2], character_only = TRUE) -#' readd(subtargets(z)[1], character_only = TRUE) -#' readd(subtargets(z)[2], character_only = TRUE) +#' readd(mean_mpg_by_cyl) #' }) #' } make <- function( diff --git a/R/manage_memory.R b/R/manage_memory.R index fb01d9b8a..ca84f22ac 100644 --- a/R/manage_memory.R +++ b/R/manage_memory.R @@ -17,6 +17,9 @@ manage_memory <- function(target, config, downstream = NULL, jobs = 1) { memory_strategy <- config$memory_strategy } class(target) <- memory_strategy + if (!is_subtarget(target, config)) { + clear_envir_subtargets(target = target, config = config) + } manage_deps( target = target, config = config, @@ -47,7 +50,6 @@ manage_deps.autoclean <- function(target, config, downstream, jobs) { target_deps <- deps_memory(targets = target, config = config) discard_these <- setdiff(x = already_loaded, y = target_deps) discard_targets(discard_these, target, config) - clear_envir_subtargets(target = target, config = config) target_deps <- setdiff(target_deps, target) target_deps <- setdiff(target_deps, already_loaded) try_load(targets = target_deps, config = config, jobs = jobs) @@ -86,7 +88,6 @@ discard_targets <- function(discard_these, target, config) { } manage_deps.unload <- function(target, config, downstream, jobs) { - clear_envir_subtargets(target = target, config = config) clear_envir_targets(target = target, config = config) } @@ -95,7 +96,6 @@ manage_deps.none <- function(target, config, downstream, jobs) { } clear_envir_subtargets <- function(target, config) { - config$logger$minor("clear subtarget envir", target = target) rm(list = config$envir_loaded$subtargets, envir = config$envir_subtargets) config$envir_loaded$subtargets <- character(0) config$envir_subtargets[[drake_envir_marker]] <- TRUE @@ -280,6 +280,7 @@ load_dynamic_subdep_impl.group <- function( # nolint ) { subdeps <- config$cache$get(dep, namespace = "meta")$subtargets[index] value <- config$cache$mget(subdeps, use_cache = FALSE) + value <- do.call(vec_c, value) assign( x = dep, value = value, diff --git a/R/package.R b/R/package.R index 8886dff53..2ee870ca8 100644 --- a/R/package.R +++ b/R/package.R @@ -29,18 +29,18 @@ #' head(large) #' } #' # Dynamic branching +#' # Get the mean mpg for each cyl in the mtcars dataset. #' plan <- drake_plan( -#' w = c("a", "a", "b", "b"), -#' x = seq_len(4), -#' y = target(x + 1, dynamic = map(x)), -#' z = target(list(y = y, w = w), dynamic = group(y, .by = w)) +#' raw = mtcars, +#' group_index = raw$cyl, +#' munged = target(raw[, c("mpg", "cyl")], dynamic = map(raw)), +#' mean_mpg_by_cyl = target( +#' data.frame(mpg = mean(munged$mpg), cyl = munged$cyl[1]), +#' dynamic = group(munged, .by = group_index) +#' ) #' ) #' make(plan) -#' subtargets(y) -#' readd(subtargets(y)[1], character_only = TRUE) -#' readd(subtargets(y)[2], character_only = TRUE) -#' readd(subtargets(z)[1], character_only = TRUE) -#' readd(subtargets(z)[2], character_only = TRUE) +#' readd(mean_mpg_by_cyl) #' }) #' } #' @references @@ -57,4 +57,5 @@ #' @importFrom txtq txtq #' @importFrom utils compareVersion flush.console head menu packageVersion #' read.csv sessionInfo stack type.convert unzip write.table +#' @importFrom vctrs vec_c vec_slice NULL diff --git a/man/drake-package.Rd b/man/drake-package.Rd index a20a60f45..be40a6c48 100644 --- a/man/drake-package.Rd +++ b/man/drake-package.Rd @@ -33,18 +33,18 @@ loadd(large) head(large) } # Dynamic branching +# Get the mean mpg for each cyl in the mtcars dataset. plan <- drake_plan( - w = c("a", "a", "b", "b"), - x = seq_len(4), - y = target(x + 1, dynamic = map(x)), - z = target(list(y = y, w = w), dynamic = group(y, .by = w)) + raw = mtcars, + group_index = raw$cyl, + munged = target(raw[, c("mpg", "cyl")], dynamic = map(raw)), + mean_mpg_by_cyl = target( + data.frame(mpg = mean(munged$mpg), cyl = munged$cyl[1]), + dynamic = group(munged, .by = group_index) + ) ) make(plan) -subtargets(y) -readd(subtargets(y)[1], character_only = TRUE) -readd(subtargets(y)[2], character_only = TRUE) -readd(subtargets(z)[1], character_only = TRUE) -readd(subtargets(z)[2], character_only = TRUE) +readd(mean_mpg_by_cyl) }) } } diff --git a/man/drake_plan.Rd b/man/drake_plan.Rd index 777da27ef..ca9f224b1 100644 --- a/man/drake_plan.Rd +++ b/man/drake_plan.Rd @@ -370,18 +370,18 @@ sms <- rlang::syms(letters) # To sub in character args, skip this. drake_plan(x = target(f(char), transform = map(char = !!sms))) # Dynamic branching +# Get the mean mpg for each cyl in the mtcars dataset. plan <- drake_plan( - w = c("a", "a", "b", "b"), - x = seq_len(4), - y = target(x + 1, dynamic = map(x)), - z = target(list(y = y, w = w), dynamic = group(y, .by = w)) + raw = mtcars, + group_index = raw$cyl, + munged = target(raw[, c("mpg", "cyl")], dynamic = map(raw)), + mean_mpg_by_cyl = target( + data.frame(mpg = mean(munged$mpg), cyl = munged$cyl[1]), + dynamic = group(munged, .by = group_index) + ) ) make(plan) -subtargets(y) -readd(subtargets(y)[1], character_only = TRUE) -readd(subtargets(y)[2], character_only = TRUE) -readd(subtargets(z)[1], character_only = TRUE) -readd(subtargets(z)[2], character_only = TRUE) +readd(mean_mpg_by_cyl) }) } } diff --git a/man/get_trace.Rd b/man/get_trace.Rd index 4d7b61331..820736fce 100644 --- a/man/get_trace.Rd +++ b/man/get_trace.Rd @@ -36,7 +36,7 @@ plan <- drake_plan( # The first trace lets us see the values of w # that go with the sub-targets of y. - y = target(c(w, x), dynamic = cross(w, x, .trace = w)), + y = target(paste0(w, x), dynamic = cross(w, x, .trace = w)), # We can use the trace as a grouping variable for the next # group(). @@ -44,12 +44,22 @@ plan <- drake_plan( # Now, we use the trace again to keep track of the # values of w corresponding to the sub-targets of z. - z = target(y, dynamic = group(y, .by = w_tr, .trace = w_tr)) + z = target( + paste0(y, collapse = "-"), + dynamic = group(y, .by = w_tr, .trace = w_tr) + ) ) make(plan) # We can read the trace outside make(). +# That way, we know which values of `w` correspond +# to the sub-targets of `y`. +readd(y) read_trace("w", "y") + +# And we know which values of `w_tr` (and thus `w`) +# match up with the sub-targets of `y`. +readd(z) read_trace("w_tr", "z") }) } diff --git a/man/id_chr.Rd b/man/id_chr.Rd index 075718f7d..f473eeabd 100644 --- a/man/id_chr.Rd +++ b/man/id_chr.Rd @@ -53,9 +53,7 @@ plan <- drake_plan( y = target(id_chr(), dynamic = map(x)) ) make(plan) -ys <- subtargets(y) -ys -readd(ys[1], character_only = TRUE) +readd(y, subtargets = 1) # Static branching plan <- drake_plan( y = target(c(x, .id_chr), transform = map(x = !!seq_len(4))) diff --git a/man/make.Rd b/man/make.Rd index 744864d32..8fc5e5460 100644 --- a/man/make.Rd +++ b/man/make.Rd @@ -631,18 +631,18 @@ vis_drake_graph(config) # The colors changed in the graph. clean() # Start from scratch next time around. } # Dynamic branching +# Get the mean mpg for each cyl in the mtcars dataset. plan <- drake_plan( - w = c("a", "a", "b", "b"), - x = seq_len(4), - y = target(x + 1, dynamic = map(x)), - z = target(list(y = y, w = w), dynamic = group(y, .by = w)) + raw = mtcars, + group_index = raw$cyl, + munged = target(raw[, c("mpg", "cyl")], dynamic = map(raw)), + mean_mpg_by_cyl = target( + data.frame(mpg = mean(munged$mpg), cyl = munged$cyl[1]), + dynamic = group(munged, .by = group_index) + ) ) make(plan) -subtargets(y) -readd(subtargets(y)[1], character_only = TRUE) -readd(subtargets(y)[2], character_only = TRUE) -readd(subtargets(z)[1], character_only = TRUE) -readd(subtargets(z)[2], character_only = TRUE) +readd(mean_mpg_by_cyl) }) } } diff --git a/man/read_trace.Rd b/man/read_trace.Rd index bbe16ecc8..cc7ca28d2 100644 --- a/man/read_trace.Rd +++ b/man/read_trace.Rd @@ -43,7 +43,7 @@ plan <- drake_plan( # The first trace lets us see the values of w # that go with the sub-targets of y. - y = target(c(w, x), dynamic = cross(w, x, .trace = w)), + y = target(paste0(w, x), dynamic = cross(w, x, .trace = w)), # We can use the trace as a grouping variable for the next # group(). @@ -51,7 +51,10 @@ plan <- drake_plan( # Now, we use the trace again to keep track of the # values of w corresponding to the sub-targets of z. - z = target(y, dynamic = group(y, .by = w_tr, .trace = w_tr)) + z = target( + paste0(y, collapse = "-"), + dynamic = group(y, .by = w_tr, .trace = w_tr) + ) ) make(plan) @@ -62,7 +65,7 @@ readd(y) read_trace("w", "y") # And we know which values of `w_tr` (and thus `w`) -# match up with the sub-targets of `z`. +# match up with the sub-targets of `y`. readd(z) read_trace("w_tr", "z") }) diff --git a/man/subtargets.Rd b/man/subtargets.Rd index 9d4729ce2..37e5c399e 100644 --- a/man/subtargets.Rd +++ b/man/subtargets.Rd @@ -38,14 +38,14 @@ plan <- drake_plan( w = c("a", "a", "b", "b"), x = seq_len(4), y = target(x + 1, dynamic = map(x)), - z = target(list(y = y, w = w), dynamic = group(y, .by = w)) + z = target(sum(x) + sum(y), dynamic = group(x, y, .by = w)) ) make(plan) subtargets(y) -readd(subtargets(y)[1], character_only = TRUE) -readd(subtargets(y)[2], character_only = TRUE) -readd(subtargets(z)[1], character_only = TRUE) -readd(subtargets(z)[2], character_only = TRUE) +subtargets(z) +readd(x) +readd(y) +readd(z) }) } } diff --git a/tests/testthat/test-9-dynamic.R b/tests/testthat/test-9-dynamic.R index 4dbf416fe..6017f5c69 100644 --- a/tests/testthat/test-9-dynamic.R +++ b/tests/testthat/test-9-dynamic.R @@ -654,7 +654,7 @@ test_with_dir("dynamic group with by", { x = target(u, dynamic = map(u)), y = target(v, dynamic = map(v)), z = target( - list(x = do.call("c", x), y = do.call("c", y), my_by = w), + list(x = x, y = y, my_by = w), dynamic = group(x, y, .by = w) ) ) @@ -672,7 +672,7 @@ test_with_dir("dynamic group with by", { x = target(u, dynamic = map(u)), y = target(v, dynamic = map(v)), z = target( - list(x = sum(do.call("c", x)), y = do.call("c", y)), + sum(c(x, y)), dynamic = group(x, y, .by = w) ) ) @@ -681,10 +681,8 @@ test_with_dir("dynamic group with by", { expect_true(all(grepl("^z", justbuilt(config)))) out1 <- readd(subtargets(z)[1], character_only = TRUE) out2 <- readd(subtargets(z)[2], character_only = TRUE) - exp1 <- list(x = 6, y = seq_len(3) + 1) - exp2 <- list(x = 4, y = 5) - expect_equal(out1, exp1) - expect_equal(out2, exp2) + expect_equal(out1, 15) + expect_equal(out2, 9) }) test_with_dir("insert .by piece by piece", { @@ -698,7 +696,7 @@ test_with_dir("insert .by piece by piece", { x = seq_len(4), y = target(x + 1, dynamic = map(x)), z = target( - list(y = unlist(y), w = w), + list(list(y = unlist(y), w = w)), dynamic = group(y, .by = w) ) ) @@ -937,27 +935,27 @@ test_with_dir("group: static targets and .by precedence", { y = target(x, dynamic = group(x)) ) make(plan) - expect_equal(readd(y), list(c("a", "a", "b", "b"))) + expect_equal(readd(y), c("a", "a", "b", "b")) plan <- drake_plan( x = c("a", "a", "b", "b"), y = seq_len(4), z = target(y, dynamic = group(y, .by = x)) ) make(plan) - expect_equal(readd(z), list(c(1, 2), c(3, 4))) + expect_equal(readd(z), c(1, 2, 3, 4)) plan <- drake_plan( x = c("a", "a", "b", "b"), y = as.character(seq_len(4)), z = target(c(x, y), dynamic = group(y, .by = x)) ) make(plan) - expect_equal(readd(z), list(c("a", "1", "2"), c("b", "3", "4"))) + expect_equal(readd(z), c("a", "1", "2", "b", "3", "4")) plan <- drake_plan( x = c("a", "a", "b", "b"), y = target(x, dynamic = group(x, .by = x)) ) make(plan) - expect_equal(readd(y), list(c("a", "a"), c("b", "b"))) + expect_equal(readd(y), c("a", "a", "b", "b")) }) test_with_dir("group multiple targets", { @@ -969,7 +967,7 @@ test_with_dir("group multiple targets", { ) make(plan) out <- readd(z) - exp <- list(list(c(1, 2), c(11, 12)), list(c(3, 4), c(13, 14))) + exp <- list(c(1, 2), c(11, 12), c(3, 4), c(13, 14)) expect_equal(out, exp) }) @@ -1006,9 +1004,7 @@ test_with_dir("non-rds formats and dynamic branching (#1059)", { y = target(x, dynamic = map(x), format = "fst") ) make(plan, session_info = FALSE) - exp <- readd(x) - out <- do.call(rbind, readd(y)) - expect_equal(out, exp) + expect_equal(readd(x), readd(y)) cache <- drake_cache() ref <- cache$storr$get("y") expect_false(inherits(ref, "drake_format_fst")) @@ -1197,32 +1193,24 @@ test_with_dir("dynamic loadd() and readd()", { y = target(x, dynamic = map(x)) ) make(plan) - out <- readd(x) - expect_equal(out, mtcars[seq_len(4), ]) + expect_equal(readd(x), mtcars[seq_len(4), ]) out <- readd(y) - expect_true(is.list(out)) - expect_false(is.data.frame(out)) - expect_equal(do.call("rbind", out), mtcars[seq_len(4), ]) + rownames(out) <- NULL + exp <- mtcars[seq_len(4), ] + rownames(exp) <- NULL + expect_equal(out, exp) skip_if_not_installed("bindr") for (lazy in c("eager", "promise", "bind")) { loadd(y, lazy = lazy) - expect_true(is.list(y)) - expect_false(is.data.frame(y)) - expect_equal(do.call("rbind", y), mtcars[seq_len(4), ]) + expect_equal(readd(y), y) rm(y) } out <- readd(y, subtargets = c(2, 4)) - expect_true(is.list(out)) - expect_false(is.data.frame(out)) - expect_equal(length(out), 2) - expect_equal(do.call("rbind", out), mtcars[c(2, 4), ]) + expect_true(is.data.frame(out)) + expect_equal(nrow(out), 2) for (lazy in c("eager", "promise", "bind")) { loadd(y, lazy = lazy, subtargets = c(2, 4)) - expect_equal(length(y), 2) - expect_true(is.list(y)) - expect_false(is.data.frame(y)) - expect_equal(do.call("rbind", y), mtcars[c(2, 4), ]) - rm(y) + expect_equal(y, out) } }) @@ -1261,7 +1249,7 @@ test_with_dir("dynamic hpc", { caching = caching ) out <- readd(groups) - exp <- list(c("aA", "aB"), c("bA", "bB")) + exp <- c("aA", "aB", "bA", "bB") expect_equal(out, exp) config <- drake_config(plan) expect_equal(outdated(config), character(0)) @@ -1294,7 +1282,7 @@ test_with_dir("dynamic hpc", { exp <- c("groups", subtargets(groups)) expect_equal(sort(out), sort(exp)) out <- readd(groups) - exp <- list(c("aA+", "aB+"), c("bA+", "bB+")) + exp <- c("aA+", "aB+", "bA+", "bB+") expect_equal(out, exp) clean(destroy = TRUE) } @@ -1332,9 +1320,9 @@ test_with_dir("dynamic max_expand", { ) expect_equal(readd(dyn1), seq_len(10)) expect_equal(readd(dyn2), seq_len(10)) - expect_equal(readd(dyn3), list(1L, 2L)) - expect_equal(readd(dyn4), list(c(1L, 1L), c(1L, 2L))) - expect_equal(readd(dyn5), list(1L, 2L)) + expect_equal(readd(dyn3), c(1L, 2L)) + expect_equal(readd(dyn4), c(1L, 1L, 1L, 2L)) + expect_equal(readd(dyn5), c(1L, 2L)) config <- drake_config(plan) make(plan, max_expand = 4) out <- justbuilt(config) @@ -1347,15 +1335,15 @@ test_with_dir("dynamic max_expand", { subtargets(dyn5)[c(3, 4)] ) expect_equal(sort(out), sort(exp)) - expect_equal(readd(dyn3), list(1L, 2L, 3L, 4L)) - expect_equal(readd(dyn4), list(c(1L, 1L), c(1L, 2L), c(1L, 3L), c(1L, 4L))) - expect_equal(readd(dyn5), list(1L, 2L, 3L, 4L)) + expect_equal(readd(dyn3), c(1L, 2L, 3L, 4L)) + expect_equal(readd(dyn4), c(1L, 1L, 1L, 2L, 1L, 3L, 1L, 4L)) + expect_equal(readd(dyn5), c(1L, 2L, 3L, 4L)) make(plan, max_expand = 3) expect_equal(sort(justbuilt(config)), sort(c("dyn3", "dyn4", "dyn5"))) expect_equal(sort(out), sort(exp)) - expect_equal(readd(dyn3), list(1L, 2L, 3L)) - expect_equal(readd(dyn4), list(c(1L, 1L), c(1L, 2L), c(1L, 3L))) - expect_equal(readd(dyn5), list(1L, 2L, 3L)) + expect_equal(readd(dyn3), c(1L, 2L, 3L)) + expect_equal(readd(dyn4), c(1L, 1L, 1L, 2L, 1L, 3L)) + expect_equal(readd(dyn5), c(1L, 2L, 3L)) suppressWarnings(rm(dyn1, dyn2, dyn3, dyn4, dyn5, envir = envir)) }) @@ -1443,7 +1431,6 @@ test_with_dir("dynamic group trace (#1052)", { expect_equal(read_trace("w_tr", "z"), LETTERS[seq_len(3)]) }) - test_with_dir("dynamic combine() does not exist", { skip_on_cran() plan <- drake_plan( @@ -1469,7 +1456,7 @@ test_with_dir("trace responds to dynamic max_expand (#1073)", { ) make(plan, max_expand = 2) expect_equal(read_trace("x", "y"), seq_len(2)) - expect_equal(readd(z), list(1, 2)) + expect_equal(readd(z), c(1, 2)) }) test_with_dir("data frame trace (#1074)", { @@ -1486,7 +1473,11 @@ test_with_dir("data frame trace (#1074)", { ) ) make(plan, max_expand = 3) - expect_equal(readd(y), unname(split(x[seq_len(3), ], f = seq_len(3)))) + out <- readd(y) + exp <- x[seq_len(3), ] + rownames(out) <- NULL + rownames(exp) <- NULL + expect_equal(out, exp) expect_equal(read_trace("x", "y"), x[seq_len(3), ]) }) @@ -1501,7 +1492,7 @@ test_with_dir("dynamic branching and memory strategies", { ) # Should clear config$envir_subtargets without a fuss. make(plan, memory_strategy = "autoclean") - expect_true(is.list(readd(z))) + expect_true(is.character(readd(z))) }) test_with_dir("format trigger for dynamic targets (#1104)", { @@ -1521,3 +1512,30 @@ test_with_dir("format trigger for dynamic targets (#1104)", { exp <- sort(c("y", subtargets(y))) expect_equal(out, exp) }) + +test_with_dir("dynamic targets are vectors (#1105)", { + plan <- drake_plan( + w = c("a", "a", "b", "b"), + x = seq_len(4), + y = target(x + 1, dynamic = map(x)), + z = target(sum(x) + sum(y), dynamic = group(x, y, .by = w)) + ) + make(plan) + expect_equal(readd(z), c(8, 16)) +}) + +test_with_dir("clear the subtarget envir for non-sub-targets", { + # Dynamic branching + # Get the mean mpg for each cyl in the mtcars dataset. + plan <- drake_plan( + raw = mtcars, + group_index = raw$cyl, + munged = target(raw[, c("mpg", "cyl")], dynamic = map(raw)), + mean_mpg_by_cyl = target( + data.frame(mpg = mean(munged$mpg), cyl = munged$cyl[1]), + dynamic = group(munged, .by = group_index) + ) + ) + make(plan) + expect_equal(nrow(readd(mean_mpg_by_cyl)), 3L) +})