为什么在将点传递给 purrr 中的映射函数时需要引用 - 取消引用点?
Why do I need to quote-unquote dots when passing them to a mapped function in purrr?
据我了解,通常您不需要在点未被修改时(例如通过更改名称)引用或取消引用点。然而,这个例子让我似乎不太明白它是如何工作的。
这里我们有一个函数,它依赖于点到 select 列的嵌套。它所做的只是从 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
具有 "wrong" 参数顺序。如果你使用 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]>
我的问题是:您需要在什么地方 condition/situation 引用和取消引用 ...
才能安全地通过函数传递它们? 以及该条件如何在这里申请?
我认为你的问题是你需要通过每个级别的函数调用传递 ...
。所以 ...
都必须通过 map()
以及你的内部函数。
我无法让您的示例与 nest()
一起使用,所以我制作了一个使用 select()
的版本
dots_fun <- function(df, foo, ...) {
df %>%
mutate(foo = foo) %>%
select(...)
}
然后,似乎您实际上无法将 as_mapper
语法与 ...
一起使用,并且通过 this github issue so you need to explicitly create an anonymous function so the iterated value isn't passed a second time in the ...
values as well. Hadley said 进行非标准评估 ~
语法只是"simple" 函数而不是 ...
函数。所以一个有效的映射函数可能看起来像这样
mapping_fun1 <- function(df, foos, ...) {
map(
.x = foos,
.f = function(x, ...) dots_fun(df = df, foo = x, ...),
...
)
}
mapping_fun1(mtcars, foos = list_of_foos, cyl, gear)
我们将 ...
传递给 map()
,通过我们的匿名函数,最后传递给 dots_fun
。如果你在任何时候打破了这条链条,它就会分崩离析。
据我了解,通常您不需要在点未被修改时(例如通过更改名称)引用或取消引用点。然而,这个例子让我似乎不太明白它是如何工作的。
这里我们有一个函数,它依赖于点到 select 列的嵌套。它所做的只是从 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
具有 "wrong" 参数顺序。如果你使用 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]>
我的问题是:您需要在什么地方 condition/situation 引用和取消引用 ...
才能安全地通过函数传递它们? 以及该条件如何在这里申请?
我认为你的问题是你需要通过每个级别的函数调用传递 ...
。所以 ...
都必须通过 map()
以及你的内部函数。
我无法让您的示例与 nest()
一起使用,所以我制作了一个使用 select()
的版本
dots_fun <- function(df, foo, ...) {
df %>%
mutate(foo = foo) %>%
select(...)
}
然后,似乎您实际上无法将 as_mapper
语法与 ...
一起使用,并且通过 this github issue so you need to explicitly create an anonymous function so the iterated value isn't passed a second time in the ...
values as well. Hadley said 进行非标准评估 ~
语法只是"simple" 函数而不是 ...
函数。所以一个有效的映射函数可能看起来像这样
mapping_fun1 <- function(df, foos, ...) {
map(
.x = foos,
.f = function(x, ...) dots_fun(df = df, foo = x, ...),
...
)
}
mapping_fun1(mtcars, foos = list_of_foos, cyl, gear)
我们将 ...
传递给 map()
,通过我们的匿名函数,最后传递给 dots_fun
。如果你在任何时候打破了这条链条,它就会分崩离析。