为 Drake 中的所有输入组合生成工作流程计划?

Generate workflow plan for all combinations of inputs in Drake?

我正在尝试创建一个工作流计划,该计划将为 my_dataset 中的所有输入组合 运行 一些功能 my_function(x, y),但我不知道如何生成命令对于 drake 的工作流程,无需使用粘贴。

考虑:

library(drake)
library(dplyr)

A <- 'apple'
B <- 'banana'
C <- 'carrot'

my_function <- function(x, y)
    paste(x, y, sep='|IT WORKS|')

my_function(A, B)

combos <- combn(c('A', 'B', 'C'), 2) %>% 
    t() %>% 
    as_data_frame()

targets <- apply(combos, 1, paste, collapse = '_')

commands <- paste0('my_function(', apply(combos, 1, paste, collapse = ', '), ')') 

my_plan <- data_frame(target = targets, command = commands)
make(my_plan)

输出:

> my_plan
# A tibble: 3 x 2
  target command          
  <chr>  <chr>            
1 A_B    my_function(A, B)
2 A_C    my_function(A, C)
3 B_C    my_function(B, C)

以上代码有效,但我使用 paste0 生成函数调用。我认为这不是最优的,而且扩展性很差。有没有更好的方法来生成这些计划?这可能不是一个 drake 问题,而是一个 rlang 问题。

免责声明:此答案说明了如何使用 rlang 框架编写表达式。但是,drake 需要命令作为字符串,因此最终的表达式需要转换为字符串。

我们首先使用 quote 捕获 ABC 作为符号,然后使用您已有的代码计算所有可能的成对组合:

CB <- combn( list(quote(A), quote(B), quote(C)), 2 ) %>% 
    t() %>% as_data_frame()
# # A tibble: 3 x 2
#   V1       V2      
#   <list>   <list>  
# 1 <symbol> <symbol>
# 2 <symbol> <symbol>
# 3 <symbol> <symbol>

我们现在可以使用purrr::map2来并行遍历两列并组成我们的表达式:

CMDs <- purrr::map2( CB$V1, CB$V2, ~rlang::expr( my_function((!!.x), (!!.y)) ) )
# [[1]]
# my_function(A, B)

# [[2]]
# my_function(A, C)

# [[3]]
# my_function(B, C)

如上所述,drake需要字符串,因此我们必须将表达式转换为:

commands <- purrr::map_chr( CMDs, rlang::quo_name )
# [1] "my_function(A, B)" "my_function(A, C)" "my_function(B, C)"

您的其余代码应该像以前一样工作。

最终,由您决定表达式算术还是字符串算术对您的应用程序更有效/更易读。另外要提到的一件事是 stringr 包,它可能使字符串运算更容易进行。

编辑

drake 现在有一个 map_plan() 函数可以做到这一点。

原版post

抱歉,我来晚了。几个月前,我在手册中的 custom metaprogramming 上添加了一节,以涵盖您提出的情况。在示例中,有一个解决方案使用 rlang/tidyeval 和一个等效解决方案使用 as.call() 创建函数调用。

现在我想到了,这个用例足够通用,我认为应该有一个简单的 map_plan() 函数来为您构建计划。我会努力的。

顺便说一句,你计划中的command列可以是语言对象的列表列而不是字符向量,但你需要一个字符列才能使用wildcard templating