我正在尝试创建一个工作流程计划,该计划将为 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
将 A
、B
和 C
捕获为符号,然后计算所有可能的成对使用您已有的代码进行组合:
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
包,它可能会让字符串算术变得更愉快。
关于r - 为 Drake 中的所有输入组合生成工作流程计划?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51886131/