将 mutate 与 map2 和 exec 一起使用而不是 invoke_map

Using mutate with map2 and exec instead of invoke_map

“R for Data Science”中的这个示例使用现已停用的 invoke_map

sim <- tribble(
  ~f, ~params,
  "runif", list(min = -1, max = 1),
  "rnorm", list(sd = 5),
  "rpois", list(lambda = 10)
)

sim %>% 
  mutate(sim = invoke_map(f, params, n = 10))

如果我单独提取列,那么它适用于 map2exec

map2(sim$f, sim$params, function(fn, args) exec(fn, !!!args, n = 10))

但是,我无法让 mutatemap2exec

一起工作
sim %>% 
  mutate(sim = map2(f, params, function(fn, args) exec(fn, !!!args, n = 10)))

我收到错误“错误:无法拼接闭包类型的对象,因为它不是向量”

有人可以帮忙吗?

我认为问题出在 exec 的某个地方,或者更具体地说,是 big-bang (!!!) 部分,由于某种原因它试图拼接不是你的变量 args,但函数 base::args(因此,您收到的错误消息)。您可以尝试将 args 重命名为其他名称,您会得到一个不同的错误:

> sim %>% 
  mutate(sim = map2(f, params, .f = function(fn, x) {exec(fn, !!!x, n = 10)}))
Error in splice(dot_call(capture_dots, frame_env = frame_env, named = named,  : 
  object 'x' not found

我必须说我还不够深入,无法解决这个问题,但如果您需要快速解决,请改用 do.call 并使用 cn = 10 拉入 args :

sim %>% 
  mutate(sim = map2(f, params, .f = function(fn, args) {do.call(fn, c(args, n = 10))}))

!!! 运算符优先于匿名函数的创建。因此,它会在数据框的范围内立即args 求值,如果找不到这样的列,则会在全局范围内求值。一种解决方案是将函数定义移到 map2 调用之外:

myfun <- function(fn, args) exec(fn, !!!args, n = 10)

sim %>% 
  mutate(sim = map2(f, params, myfun))        # Now works

另一种解决方案是将函数名称和所有参数连接到一个列表中,然后将该列表及其 domain lifted:

传递给 exec
sim %>%
    mutate(temp = map2(f, params, c, n=10),
           sim  = map(temp, lift(exec)),
           temp = NULL)