0

再现性数据

.i <- tibble(a=2*1:4+1, b=2*1:4)

该函数应该将其数据和其他参数作为不带引号的名称,在数据中找到这些名称,并使用它们添加一列并过滤掉第一行。这没用。变异说找不到了。

t1 <- function(.j=.i, X=a, Y=b){
  e_X <- enquo(X)
  e_Y <- enquo(Y)
  mutate(.data=.j, pass=UQ(e_X)+1) %>% 
    filter(UQ(e_Y) > 3) -> out
  out
}
t1(a,b)

这个函数,我是通过拼写错误找到的——注意 mutate 语句中的 .i 而不是 .j ——完成了前一个函数应该做的事情。我不知道为什么。我认为它正在跳过函数参数并在全局环境中查找 .i 。或者也许它正在使用一个ouiji板。

t2 <- function(.j=.i, X=a, Y=b){
  e_X <- enquo(X)
  e_Y <- enquo(Y)
  mutate(.data=.i, pass=UQ(e_X)+1) %>% 
  filter(UQ(e_Y) > 3) -> out
  out
}
t1(a,b)

由于 mutate 在以通常的 R 方式传递给它时找不到 .j,因此可能需要以 rlang 样式的 quosure 传递,就像形式 X 和 Y 一样。这个函数也不起作用,UQ in mutate 说它找不到了。与上面的第一个函数一样,如果将 mutate 中的 .j 替换为 .i,它就会起作用。(似乎应该有一个平行现状的“enquos”)。

t3 <- function(.j=.i, X=a, Y=b){
  e_j <- enquo(.j)
  e_X <- enquo(X)
  e_Y <- enquo(Y)
  mutate(.data=UQ(.j), pass=UQ(e_X)+1) %>% 
    filter(UQ(e_Y) > 3) -> out
  out
}
t1(a,b)

最后,似乎一旦在 mutate 中进行了 .i 替换,t4() 就不再需要数据参数了。见下文,我将其替换为 bop_foo_foo。但是,如果您将 bop_foo_foo 全部替换为数据名称 .i, (t5()),则 UQ 再次无法找到 a。

bop_foo_foo <- 0
t4 <- function(bop_foo_foo, X=a, Y=b){
  e_j <- enquo(bop_foo_foo)
  e_X <- enquo(X)
  e_Y <- enquo(Y)
  mutate(.data=UQ(.i), pass=UQ(e_X)+1) %>% 
    filter(UQ(e_Y) > 3) -> out
  out
}
t1(a,b)

在我看来,上面的函数似乎是单个函数的相对较小的变体。我又跑了几十次,虽然我观察到了一些模式,并且阅读了不知道多少遍的 enquo 和 UQ 帮助文件,但我仍然无法真正理解。

我想知道为什么上面那些不起作用的功能不起作用,以及为什么起作用的功能起作用。我不一定需要一个功能一个功能的批评。如果您能陈述体现所需理解的一般原则,那将是令人愉快的。而且绰绰有余。

4

1 回答 1

1

我认为它正在跳过函数参数并在全局环境中查找 .i 。

是的,R 中的符号范围是分层的。首先查找函数的局部变量,然后检查函数的周围环境,依此类推。

变异(.data = UQ(.j),...)

我认为您缺少常规参数和(准)引用参数之间的区别。取消引用仅与准引用参数相关。由于 的.data论点mutate()不是准引用的,因此尝试取消引用内容是没有意义的。quasiquoted 参数是用enexpr()or捕获/引用的参数enquo()。您可以通过查看文档或通过识别参数支持对列的直接引用来判断参数是否被 quasiquoted(常规参数需要明确说明在哪里可以找到列)。

在 rlang 的下一个版本中,导出的UQ()函数会抛出一个错误,以明确不应该直接调用它,并且只能在 quasiquoted arguments 中使用。

我会建议:

  • 调用函数的第一个参数datadf而不是.i.
  • 不要给它一个默认值。用户应始终提供数据。
  • 不要用enquo()orenexpr()或捕获它substitute()。而是将其直接传递给其他动词的数据参数。

一旦解决了这个问题,剩下的就更容易解决了。

于 2017-12-18T18:15:26.903 回答