dplyr,rlang:无法预测传递名称到嵌套dplyr函数的次要变体是否有效

问题描述 投票:0回答:1

数据的再现性

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

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

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)

这个函数,我通过拼写错误发现 - 注意.i而不是.j在mutate语句中 - 执行前一个函数应该做的事情。我不知道为什么。我认为它正在跳过函数参数并在全局环境中查找.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说它找不到了。与上面的第一个函数一样,如果mut中的.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替换它。但是,如果你用数据名称.i,(t5())替换bop_foo_foo,那么UQ再次找不到。

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帮助文件,我不知道多少次,但真正的理解仍然无法实现。

我想知道为什么上面那些不起作用的功能不起作用,为什么那些起作用的功能呢。我不一定需要函数批判的功能。如果你能说出体现所需要的理解的一般原则,那将是令人愉快的。绰绰有余。

r quote rlang non-standard-evaluation
1个回答
1
投票

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

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

变化(。数据= UQ(J),...)

我认为你错过了常规参数和(准)引用参数之间的区别。 Unquoting仅与quasiquoted参数相关。由于.datamutate()论证不是准引号,因此尝试和取消引用内容是没有意义的。准引用的参数是用enexpr()enquo()捕获/引用的参数。您可以通过查看文档或通过识别参数支持对列的直接引用来判断参数是否是准引号(常规参数需要明确指出列的位置)。

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

我会建议:

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

一旦这样做了,就可以更容易地解决剩下的问题了。

© www.soinside.com 2019 - 2024. All rights reserved.