【发布时间】:2020-03-04 01:19:42
【问题描述】:
据我了解,通常您不需要在未修改点时引用或取消引用点(例如通过更改名称)。然而,这个例子让我觉得我并不真正理解它是如何工作的。
这里我们有一个函数,它依靠点来选择列进行嵌套。它所做的只是从foo 参数中添加一列,然后嵌套点中未提及的所有列。
library(tidyverse)
dots_fun <- function(df, foo, ...) {
df %>%
mutate(foo = foo) %>%
nest(data = -c(...))
}
dots_fun(mtcars, "a", cyl)
#> # A tibble: 3 x 2
#> cyl data
#> <dbl> <list>
#> 1 6 <tibble [7 × 11]>
#> 2 4 <tibble [11 × 11]>
#> 3 8 <tibble [14 × 11]>
我希望能够映射这个函数,通过使用不同的参数调用它。使用普通匿名函数语法的天真方法会失败并出现令人困惑的错误:
list_of_foos <- c("a", "b")
mapping_fun1 <- function(df, foos, ...) {
map(
.x = foos,
.f = ~ dots_fun(df = df, foo = .x, ...)
)
}
mapping_fun1(mtcars, foos = list_of_foos, cyl)
#> Error: Can't subset columns that don't exist.
#> x The column `a` doesn't exist.
如果我只是将点移到匿名函数之外,也无济于事。它不再出错,但无法根据需要嵌套在 cyl 上。
mapping_fun2 <- function(df, foos, ...) {
map(
.x = foos,
.f = ~ dots_fun(df = df, foo = .x),
...
)
}
mapping_fun2(mtcars, foos = list_of_foos, cyl)
#> [[1]]
#> # A tibble: 1 x 1
#> data
#> <list>
#> 1 <tibble [32 × 12]>
#>
#> [[2]]
#> # A tibble: 1 x 1
#> data
#> <list>
#> 1 <tibble [32 × 12]>
我设法通过将点拼接到匿名函数中来使其工作,但我真的不明白为什么这是必要的。 (您也可以通过反转映射函数的参数顺序并通过map 的... 提供所有参数来使其工作,但是dots_fun 具有“错误”的参数顺序。它没有如果您使用 function() 样式的匿名函数来反转参数顺序,则可以使用)
mapping_fun3 <- function(df, foos, ...) {
dots <- enquos(...)
map(
.x = foos,
.f = ~ dots_fun(df = df, foo = .x, !!!dots)
)
}
mapping_fun3(mtcars, foos = list_of_foos, cyl)
#> [[1]]
#> # A tibble: 3 x 2
#> cyl data
#> <dbl> <list>
#> 1 6 <tibble [7 × 11]>
#> 2 4 <tibble [11 × 11]>
#> 3 8 <tibble [14 × 11]>
#>
#> [[2]]
#> # A tibble: 3 x 2
#> cyl data
#> <dbl> <list>
#> 1 6 <tibble [7 × 11]>
#> 2 4 <tibble [11 × 11]>
#> 3 8 <tibble [14 × 11]>
我的问题是:您需要在什么条件/情况下引用和取消引用 ... 才能安全地将它们传递给函数?该条件在这里如何适用?
【问题讨论】:
-
您使用的是哪个版本的
tidyr?调用dots_fun(mtcars, "a", cyl)时出现错误(cyl未找到)。我用tidyr_1.0.2 -
我认为问题与您需要通过
map和内部函数传递省略号的事实有关:stackoverflow.com/questions/48215325/… 但我很难复制。