Проходя,,в `map ()` используя tidyeval - PullRequest
2 голосов
/ 03 июня 2019

Я хочу передать точки ... моему map(), используя задание, чтобы я мог оценить предоставленный аргумент.

Передача ... напрямую работает, но цитирование ... и соединение с использованием !!! вызывает ошибку.

Я пробовал использовать различные функции rlang, например syms, quos, enquos и т. Д. Я приложил все усилия, чтобы прочитать главы 17-20 Advanced-R.

Я создал функцию 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 в вызове карты?

1 Ответ

1 голос
/ 03 июня 2019

Нет способа сделать это с 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
...