如何使用dplyr和省略号(dots elipse)编写嵌套函数?

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,但我已经受够了,需要你的帮助。
编辑:Chris发现了一个聪明而简单的技巧来修正我的foo.each函数。在这种情况下,有没有更自然的方法处理...省略号?
例如,在函数开始时是否有更好的方法获取args
  args <- sapply(substitute(list(...))[-1], deparse)

1
有时我也会对此感到厌烦。foo(df, !!sym(args[i]), !!sym(args[j])) %>% print 是否达到了你的预期? - Chris
是的!!! 你做到了... 把它写成答案,我会接受它。 - pietrodito
1个回答

4

您的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
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接