代码之家  ›  专栏  ›  技术社区  ›  pedram

为德雷克的所有输入组合生成工作流计划?

  •  2
  • pedram  · 技术社区  · 6 年前

    my_function(x, y) 所有输入组合 my_dataset 但是对于如何在不使用粘贴的情况下为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生成函数调用。我不认为这是最佳的,它的规模很差。有没有更好的方法来制定这些计划?这可能不是一个德雷克式的问题,而是一个 rlang 问题。

    2 回复  |  直到 6 年前
        1
  •  2
  •   Artem Sokolov    6 年前

    免责声明:这个答案展示了如何使用 rlang 框架。然而, drake 需要将命令作为字符串,因此需要将最终表达式转换为字符串。

    我们从抓捕开始 A B C quote ,然后使用已有的代码计算所有可能的成对组合:

    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)
    

    如上所述, 公鸭

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

    剩下的代码应该像以前一样工作。

    最终,由您决定表达式算术还是字符串算术对您的应用程序来说更有效/更可读。还有一件事要提的是 stringr 包,这可能会使字符串运算更容易完成。

        2
  •  1
  •   landau    6 年前

    编辑

    drake 现在有一个 map_plan() 做这个的功能。

    原职

    对不起,我来晚了。几个月前,我在手册中增加了一节 custom metaprogramming 在手册中介绍你所提出的情况。在本例中,有一个解决方案使用 rlang /tidyeval及其等价解 as.call()

    现在我想到了,这个用例已经足够通用了,我认为应该有一个简单的 地图计划() 为您制定计划的功能。我会努力的。

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

    推荐文章