我不清楚何时可以在 pmap() 和 pwalk() 的.l参数中明确配对参数。有时,这些 purrr 函数似乎仅在提供给它们的数据帧具有直接映射到名为 in 的函数的预期参数的名称时才起作用.f。其他时候可以将完整的数据帧提供给 pmap() 并且可以显式地对变量进行配对映射。
library(dplyr)
library(purrr)
library(tibble)
set.seed(57)
ds_mt <-
mtcars %>%
rownames_to_column("model") %>%
mutate(am = factor(am, labels = c("auto", "manual"))) %>%
select(model, mpg, wt, cyl, am) %>%
sample_n(3)
foo <- function(model, am, mpg){
print(
paste("The", model, "has a", am, "transmission and gets", mpg, "mpgs.")
)
}
Run Code Online (Sandbox Code Playgroud)
为什么这些代码块有效?
ds_mt %>%
select(model, am, mpg) %>%
pwalk(
.l = .,
.f = foo
)
# example with explicit pair mapping
ds_mt %>%
mutate(
new_var =
pmap(
.l = list(model=model, am=am, mpg=mpg),
.f = foo
)
)
Run Code Online (Sandbox Code Playgroud)
虽然这些代码块失败了?
ds_mt %>%
pwalk(
.l = list(model, am, mpg),
.f = foo
)
ds_mt %>%
pwalk(
.l = list(model=model, am=am, mpg=mpg),
.f = foo
)
Run Code Online (Sandbox Code Playgroud)
您的问题与pmap()或无关pwalk()。它源于对管道和mutate()函数如何工作的一些误解。
一、管道:
除非另外用点指定,否则管道将左侧 (LHS) 作为函数右侧 (RHS) 的第一个参数传递。
所以这有效:
ds_mt %>%
select(model, am, mpg) %>%
pwalk(
.l = .,
.f = foo
)
Run Code Online (Sandbox Code Playgroud)
因为您的列表(= 您的数据框,因为数据框是向量列表),即管道的 LHS,用作pwalk()RHS 上的第一个参数。
在这种情况下,您实际上不需要点,您可以更简单地将其写为:
ds_mt %>%
select(model, am, mpg) %>%
pwalk(foo)
Run Code Online (Sandbox Code Playgroud)
另一方面,当您尝试运行时:
ds_mt %>%
pwalk(
.l = list(model, am, mpg),
.f = foo
)
Run Code Online (Sandbox Code Playgroud)
LHS 和 RHS 之间的连接不遵循管道规则,因此 R 不知道是什么model,因为您没有任何名为model.
为了使这个表达式起作用,您可以在没有管道的情况下以这种方式编写它:
pwalk(
.l = list(ds_mt$model, ds_mt$am, ds_mt$mpg),
.f = foo
)
Run Code Online (Sandbox Code Playgroud)
或者,如果你想使用管道,你必须用点替换管道的 LHS(因为它没有作为 RHS 上函数的第一个参数传递),这是代码工作所必需的,但在这里,由于您在嵌套函数中传递 LHS,因此您还必须将 RHS 放在大括号之间,否则 R 会将 LHS 作为 RHS 最外层函数的第一个参数传递:
ds_mt %>% {
pwalk(
.l = list(.$model, .$am, .$mpg),
.f = foo
)
}
Run Code Online (Sandbox Code Playgroud)
或者,以更紧凑的风格:
ds_mt %>% {pwalk(list(.$model, .$am, .$mpg), foo)}
Run Code Online (Sandbox Code Playgroud)
总之,在管道的 LHS 上有一个对象是不够的,R 将它神奇地应用于 RHS 的正确位置(但我认为您的困惑可能来自dplyr函数的情况(见下文))。默认情况下,它用作 RHS 上函数的第一个参数(在这种情况下,您不需要任何点)。对于其他展示位置,您确实需要在需要 LHS 的每个位置处加一个点。并且在嵌套函数的情况下(如您在此处所见),您还需要将 RHS 括在花括号中,否则 R 会将 LHS 作为最外层 RHS 函数的第一个参数传递。
现在,以您的mutate()示例为例:
ds_mt %>%
mutate(
new_var = pmap(
.l = list(model, am, mpg),
.f = foo
)
)
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为使用较新版本的dplyr,在调用mutate()函数内部的变量时不再需要数据框和美元符号。所以在这里,R 并不想知道什么model是因为您处于“变异框架”中,可以这么说,并且 R 理解model为含义.$model或ds_mt$model。所以在这里,这与pmap()或无关,pwalk()而是dplyr函数的特殊性(与 相同summarise())。我想dplyr函数允许的这种记法快捷方式会导致您感到困惑。
最后,您所说的“显式对映射”没有任何效果。由于您将函数定义foo()为接受 3 个参数,只要您将参数保持在正确的顺序,
foo(model = model, am = am, mpg = mpg)
Run Code Online (Sandbox Code Playgroud)
和
foo(model, am, mpg)
Run Code Online (Sandbox Code Playgroud)
完全一样。但是,如果您交换参数,则确实需要明确。例如:
foo(am = am, model = model, mpg = mpg)
Run Code Online (Sandbox Code Playgroud)