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

如何用dplyr和dots-elipse编写嵌套函数?

  •  7
  • pietrodito  · 技术社区  · 7 年前

    我尽量把这个简单化

    一些示例数据:

    library(magrittr)
    library(dplyr)
    library(rlang)
    
    # sample data
    tib <- tibble(
      a = 1:3,
      b = 4:6,
      c = 7:9
    )
    

    现在是一个函数,它将两列相加:

    foo = function(df, x, y) {
    
      x <- enquo(x)
      y <- enquo(y)
    
      df %>% 
       select( !! x, !! y) %>% 
       mutate(sum = !! x + !! y) 
    }
    

    希望能奏效:

    foo(tib, a, b) # to show it works
    
    # A tibble: 3 x 3
    #       a     b   sum
    #   <int> <int> <int>
    # 1     1     4     5
    # 2     2     5     7
    # 3     3     6     9
    

    现在我想写第二个函数 foo 对于所有可能的参数对:

    foo.each(tib, a, b, c) 
    # calls foo(tib, a, b)
    # calls foo(tib, a, c)
    # calls foo(tib, b, c)
    # i.e calls foo for each possible pair
    

    我试过,但那不管用:

    foo.each = function(df, ...) {
      args <- sapply(substitute(list(...))[-1], deparse)
      args
    
      nb.args <- args %>% length
      for (i in nb.args:2)
        for (j in 1:(i - 1))
          foo(df, args[i], args[j]) %>% print
    }
    

    问题在foo内部:

       mutate(sum = !! x + !! y) 
    

    我认为它被评估为:

      mutate(sum = args[i] + args[j])
    

    rlang::quos 但我受够了,我需要你的帮助。


    编辑 :克里斯发现了一个聪明而简单的技巧来纠正我 foo.each ... 在这种情况下是不是消失了?

    例如,有没有更好的方法 args 在函数开始的时候?

      args <- sapply(substitute(list(...))[-1], deparse)
    
    1 回复  |  直到 6 年前
        1
  •  4
  •   Chris    7 年前

    你的 foo args[i] 对它来说是弦。

    sym 不引用 !!

    foo.each = function(df, ...) {
      args <- sapply(substitute(list(...))[-1], deparse)
      args
    
      nb.args <- args %>% length
      for (i in nb.args:2)
        for (j in 1:(i - 1))
          foo(df, !!sym(args[i]), !!sym(args[j])) %>% print
    }
    
    推荐文章