路过。 . .使用 tidyeval 到 `map()`

Passing . . . to `map()` using tidyeval

我想使用 quosure 将点 ... 传递给我的 map() 以便我可以评估提供的参数。

直接传...就可以,但是引用...并用!!!拼接会报错

我尝试使用各种 rlang 函数,即 symsquosenquos 等。我已尽最大努力通读 Advanced-R 第 17 章- 20.

我创建了一个函数 f,它从 n 之前的每个数字的随机正态分布中提取数据。我可以使用点将其他参数传递给 rnorm()。这很好用。

library(magrittr)
library(purrr)


f <- function(n, ...) {
1:n %>% 
  map(rnorm, ...)
}


f(2, mean = 10)
#> 
#> [[1]]
#> [1] 10.90561
#> 
#> [[2]]
#> [1] 11.19031 12.16856
f(2)
#> [[1]]
#> [1] -1.197873
#> 
#> [[2]]
#> [1]  1.023398 -2.023645

我创建了第二个函数 g(),它的目的是做同样的事情,但使用 tidy eval。

g <- function(n, ...) {

  1:n %>% 
    map(rnorm, !!!enquos(...))
}

g(3)

#> 
#> [[1]]
#> [1] NA
#> 
#> [[2]]
#> [1] NA NA
#>
#> Warning messages:
#> 1: In .f(.x[[i]], ...) : NAs produced
#> 2: In .f(.x[[i]], ...) : NAs produced

这个实现产生 NA.

我已尝试为此使用 list2(),但仍然无法对其进行评估。有没有办法在地图调用中使用 tidyeval 评估点?

purrr::map() 无法做到这一点。这些点按原样传递给映射函数,没有任何更改。因此,映射函数的责任是通过使用 enquos()list2().

捕获 ... 来实现整洁的点

你可以做的是创建你自己的映射函数,它接受带 !!! 支持的点,创建一个带有拼接参数的调用,以及调用输入的映射:

map_splice <- function(.x, .f, ...) {
  n <- length(.x)
  out <- vector("list", n)

  # Capture arguments with `!!!` support
  args <- list2(...)

  # Create call with arguments spliced in
  call <- expr(.f(.x[[i]], !!!args))

  for (i in seq_len(n)) {
    out[[i]] <- eval(call)
  }

  out
}

h <- function(n, ...) {
  map_splice(seq_len(n), rnorm, ...)
}

h(3)
#> [[1]]
#> [1] 0.198766
#>
#> [[2]]
#> [1]  0.99824414 -0.08231719
#>
#> [[3]]
#> [1]  0.5288825 -0.6098536  0.7858720

args <- list(mean = 50, sd = 3)
h(3, !!!args)
#> [[1]]
#> [1] 49.32423
#>
#> [[2]]
#> [1] 57.51101 46.69594
#>
#> [[3]]
#> [1] 53.80943 50.00880 54.96616