【问题标题】:Supplying the list argument to .l in pmap() or pwalk()在 pmap() 或 pwalk() 中为 .l 提供列表参数
【发布时间】:2018-11-27 06:11:34
【问题描述】:

我不清楚参数何时可以在 pmap() 和 pwalk() 的 .l 参数中显式配对。有时,这些 purrr 函数似乎仅在提供给它们的数据帧的名称直接映射到 .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.")
  )
}

为什么这些代码块有效?

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
      )
  )

虽然这些代码块失败了?

ds_mt %>% 
  pwalk(
  .l = list(model, am, mpg),
  .f = foo
)

ds_mt %>% 
  pwalk(
  .l = list(model=model, am=am, mpg=mpg),
  .f = foo
)

【问题讨论】:

  • 你的变异示例对我不起作用
  • 知道了:我认为您有错字并且缺少list()
  • 谢谢,我已更正了错字。感谢您的彻底回应。
  • 我的荣幸。我希望它有所帮助。我通过删除关于那个错字的(现在没用的)部分来编辑我的答案。

标签: r purrr


【解决方案1】:

您的问题与pmap()pwalk() 无关。它源于对管道和mutate() 函数如何工作的一些误解。


首先是管道:

除非用点另外指定,否则管道将左侧 (LHS) 作为右侧 (RHS) 函数的第一个参数传递。

所以这行得通:

ds_mt %>% 
  select(model, am, mpg) %>% 
  pwalk(
    .l = .,
    .f = foo
  )

因为您的列表(= 您的数据框,因为数据框是向量列表),即管道的 LHS,被用作 RHS 上 pwalk() 的第一个参数。

在这种情况下,您实际上不需要点,您可以更简单地写成:

ds_mt %>% 
  select(model, am, mpg) %>% 
  pwalk(foo)

另一方面,当你尝试运行时:

ds_mt %>% 
  pwalk(
    .l = list(model, am, mpg),
    .f = foo
  )

LHS 和 RHS 之间的连接不遵循管道规则,因此 R 不知道 model 是什么,因为您没有任何名为 model 的对象。

为了使这个表达式起作用,你可以用这种方式编写它,而不用管道:

pwalk(
  .l = list(ds_mt$model, ds_mt$am, ds_mt$mpg),
  .f = foo
)

或者,如果你想使用管道,你必须用点替换管道的 LHS(因为它没有作为 RHS 上函数的第一个参数传递),这是代码工作所必需的,但是在这里,由于您在嵌套函数中传递 LHS,因此您还必须将 RHS 放在大括号之间,否则 R 会将 LHS 作为 RHS 最外层函数的第一个参数传递:

ds_mt %>% {
  pwalk(
    .l = list(.$model, .$am, .$mpg),
    .f = foo
  )
}

或者,以更紧凑的风格:

ds_mt %>% {pwalk(list(.$model, .$am, .$mpg), foo)}

总之,仅仅在管道的 LHS 上有一个对象,让 R 神奇地将它应用到 RHS 的正确位置是不够的(但我认为你的困惑可能来自 dplyr 函数的情况(见下文))。默认情况下,它用作 RHS 上函数的第一个参数(在这种情况下,您不需要任何点)。对于其他展示位置,您确实需要在每个需要 LHS 的地方放置一个点。在嵌套函数的情况下(如您在此处所使用的),您还需要将 RHS 括在花括号中,否则 R 会将 LHS 作为最外层 RHS 函数的第一个参数传递。


现在,以您的mutate() 为例:

ds_mt %>% 
  mutate(
    new_var = pmap(
      .l = list(model, am, mpg),
      .f = foo
    )
  )

此方法之所以有效,是因为对于较新版本的dplyr,在mutate() 函数内调用变量时不再需要数据框和美元符号。所以在这里,R 并不奇怪model 是什么,因为可以这么说,因为您处于“变异框架”中,R 将model 理解为意味着.$modelds_mt$model。所以在这里,这与pmap()pwalk() 无关,而是dplyr 函数的特殊性(与summarise() 相同)。我想dplyr 函数允许的这种表示法的快捷方式会导致您感到困惑。


最后,你所说的“显式对映射”没有效果。由于您将函数 foo() 定义为接受 3 个参数,因此只要保持参数顺序正确,

foo(model = model, am = am, mpg = mpg)

foo(model, am, mpg)

完全一样。但是,如果您交换参数,则确实需要明确。例如:

foo(am = am, model = model, mpg = mpg)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-12-22
    • 2013-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-28
    • 2021-03-05
    相关资源
    最近更新 更多