首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >传球。。。到使用tidyeval的` `map()`

传球。。。到使用tidyeval的` `map()`
EN

Stack Overflow用户
提问于 2019-06-03 09:20:53
回答 1查看 160关注 0票数 4

我想使用quosure将点...传递给我的map(),这样我就可以计算所提供的参数。

直接传递...是可行的,但是引用...并使用!!!拼接会导致错误。

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

我已经创建了一个函数f,它从一个随机正态分布中提取直到n为止的每个数字。我可以使用点将其他参数传递给rnorm()。这可以很好地工作。

代码语言:javascript
复制
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(),它的目的是做同样的事情,但是使用了整洁的eval。

代码语言:javascript
复制
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()来解决这个问题,但仍然无法对其进行评估。有没有办法在map调用中使用tidyeval来评估这些点?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-06-03 14:50:50

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

您可以做的是创建自己的映射函数,该函数使用!!!支持获取点,使用拼接的参数创建调用,并映射对输入的调用:

代码语言:javascript
复制
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
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56420159

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档