Drake: как отправить аргументы цели с помощью комбайна?

Рассмотрим следующий MWE. Как мне получить целые числа m1 и m2 вместо выражений, которые будут представлены аргументам func () вместо «объект '1' не найден»?

func <- function(x, m1, m2) {
  paste("M1=", m1, "M2=", m2, ": ", mean(unlist(x)))
}
p <- drake_plan(
  a = target(
    runif(10, m1, m2),
    transform = cross(m1 = 0, m2 = c(1,2), n = !!c(1,5))
  ),
  b = target(
    func(list(a), m1, m2),
    transform = combine(a, .by = m2)
  )
)

person adamski    schedule 07.11.2019    source источник


Ответы (1)


!!as.numeric(deparse(substitute())) делает то, что я думаю, ты хочешь.

library(drake)

f <- function(x, m1, m2) {
  paste("M1 = ", m1, "M2 = ", m2, ": ", mean(unlist(x)))
}

plan <- drake_plan(
  a = target(
    runif(10, m1, m2),
    transform = cross(m1 = 0, m2 = c(1, 2), n = c(1, 5))
  ),
  b = target(
    f(
      list(a),
      !!as.numeric(deparse(substitute(m1))),
      !!as.numeric(deparse(substitute(m2)))
    ),
    transform = combine(a, m1, m2, .by = m2)
  )
)

plan
#> # A tibble: 6 x 2
#>   target  command                        
#>   <chr>   <expr>                         
#> 1 a_0_1_1 runif(10, 0, 1)                
#> 2 a_0_2_1 runif(10, 0, 2)                
#> 3 a_0_1_5 runif(10, 0, 1)                
#> 4 a_0_2_5 runif(10, 0, 2)                
#> 5 b_1     f(list(a_0_1_1, a_0_1_5), 0, 1)
#> 6 b_2     f(list(a_0_2_1, a_0_2_5), 0, 2)

make(plan)
#> target a_0_2_5
#> target a_0_2_1
#> target a_0_1_1
#> target a_0_1_5
#> target b_2
#> target b_1

readd(b_1)
#> [1] "M1 =  0 M2 =  1 :  0.546001701243222"

readd(b_2)
#> [1] "M1 =  0 M2 =  2 :  1.12784601158928"

Создано 7 ноября 2019 г. пакетом REPEX (v0.3.0)

NB development drake теперь имеет динамическое ветвление, которое полностью исключает метапрограммирование.

library(drake)

plan <- drake_plan(
  min = rep(c(1, 10), times = 2),
  max = rep(c(100, 1000), each = 2),
  range = target(
    range(runif(1000, min, max)),
    dynamic = map(min, max)
  ),
  out = target(
    list(range = range, min = min, max = max),
    dynamic = combine(range, min, max, .by = max)
  )
)

plan
#> # A tibble: 4 x 3
#>   target command                             dynamic                       
#>   <chr>  <expr>                              <expr>                        
#> 1 min    rep(c(1, 10), times = 2)          … NA                           …
#> 2 max    rep(c(100, 1000), each = 2)       … NA                           …
#> 3 range  range(runif(1000, min, max))      … map(min, max)                …
#> 4 out    list(range = range, min = min, max… combine(range, min, max, .by …

make(plan)
#> target max
#> target min
#> dynamic range
#> subtarget range_1d8ef6a7
#> subtarget range_b7af4aa4
#> subtarget range_4f5b896d
#> subtarget range_36590ee2
#> dynamic out
#> subtarget out_6d655424
#> subtarget out_79642dc2

str(readd(out))
#> List of 2
#>  $ :List of 3
#>   ..$ range:List of 2
#>   .. ..$ : num [1:2] 1.19 99.89
#>   .. ..$ : num [1:2] 10 99.9
#>   ..$ min  : num [1:2] 1 10
#>   ..$ max  : num [1:2] 100 100
#>  $ :List of 3
#>   ..$ range:List of 2
#>   .. ..$ : num [1:2] 2.95 999.07
#>   .. ..$ : num [1:2] 10.6 999.4
#>   ..$ min  : num [1:2] 1 10
#>   ..$ max  : num [1:2] 1000 1000

Создано 7 ноября 2019 г. пакетом REPEX (v0.3.0)

ИЗМЕНИТЬ 2019-11-08: ответ на комментарий

Вот рабочий пример, который показывает, что происходит с планом, который вы предложили в комментарии.

library(drake)
func <- function(x, min, max) {
  obs_mins <- vapply(x[[1]], min, FUN.VALUE = numeric(1))
  obs_maxes <- vapply(x[[1]], max, FUN.VALUE = numeric(1))
  c(
    paste("true mins =", paste(min, collapse = " ")),
    paste("observed mins =", paste(obs_mins, collapse = " ")),
    paste("true maxes =", paste(max, collapse = " ")),
    paste("observed maxes =", paste(obs_maxes, collapse = " "))
  )
}

plan <- drake_plan(
  min = rep(c(1, 10), times = 2),
  max = rep(c(100, 1000), each = 2),
  range = target(
    runif(1000, min, max),
    dynamic = map(min, max)
  ),
  out = target(
    func(list(range), min, max),
    dynamic = combine(range, min, max, .by = max)
  )
)

make(plan)
#> target max
#> target min
#> dynamic range
#> subtarget range_1d8ef6a7
#> subtarget range_b7af4aa4
#> subtarget range_4f5b896d
#> subtarget range_36590ee2
#> dynamic out
#> subtarget out_f77512dc
#> subtarget out_6cdbf87f

readd(out)
#> [[1]]
#> [1] "true mins = 1 10"                                  
#> [2] "observed mins = 1.1893078815192 10.0397920585237"  
#> [3] "true maxes = 100 100"                              
#> [4] "observed maxes = 99.8936234710272 99.9091432918794"
#> 
#> [[2]]
#> [1] "true mins = 1 10"                                  
#> [2] "observed mins = 2.94825347024016 10.5835021450184" 
#> [3] "true maxes = 1000 1000"                            
#> [4] "observed maxes = 999.074836849002 999.377815874759"

Создано 8 ноября 2019 г. пакетом REPEX (v0.3.0)

person landau    schedule 08.11.2019
comment
Я забыл упомянуть, что динамическое ветвление в настоящее время доступно только в разрабатываемой версии: https; // github.com/ropensci/drake - person landau; 08.11.2019
comment
Спасибо! Эта вторая альтернатива прекрасна :), с нетерпением жду релиза! - person adamski; 08.11.2019
comment
Хорошо, не уверен, что я получаю динамику, это не работает: `` `` func ‹- function (x, m1, m2) {paste (M1 =, m1, M2 =, m2,:, mean (unlist (x)) )} план ‹- drake_plan (min = rep (c (1, 10), times = 2), max = rep (c (100, 1000), each = 2), range = target (runif (1000, min, max) ), dynamic = map (min, max)), out = target (func (list (range), min, max), # list (range = range, min = min, max = max), dynamic = comb (range, min, max, .by = max)), trace = TRUE) make (plan) `` Принимает среднее значение по всему диапазону вместо максимального - person adamski; 08.11.2019
comment
См. Редактирование. Когда вы вызываете func(), он действует одновременно на 2 подцели. Каждый элемент x[[1]] - это вектор однородных случайных чисел. - person landau; 08.11.2019
comment
Не могли бы вы разместить дополнительные вопросы на странице github.com/ropensci/drake/issues? Stack Overflow не предназначен для расширенных обсуждений. - person landau; 08.11.2019