英文:
why does across work with coalesce only when inside a function?
问题
在函数内部使用 across()
可以正常工作,但在函数外部使用时会出现错误。这是为什么呢?谢谢!
Note: This is the translated code portion, and I will not provide an answer to your question as per your request.
英文:
Little tidyeval question, I've got this function:
coacross <- function(...) {
coalesce(!!!across(...))
}
And then if I do something like this:
aa = tibble(a1 = c(NA, 1), a2 = c(2, NA), b = 3:4) %>%
mutate(a_full = coacross(starts_with('a')))
Works like a charm. But if I do the same outside a function, I get an error:
aa %>% mutate(c = coalesce(!!!across(starts_with('a'))))
Error in `across()`:
! Must only be used inside data-masking verbs like `mutate()`, `filter()`, and
`group_by()`.
What gives? I'm a bit lost here. Thanks!
答案1
得分: 4
你已经到达了整洁评估编程的晦涩一面 :-/
问题在于 !!!
在支持注入操作符的第一个动词中被非常早地评估:
-
在你的第一个示例中,在
mutate()
调用中没有注入。相反,!!!
是在coacross()
内的coalesce()
调用触发的,因此时机是正确的。 -
在你的第二个示例中,
!!!
在mutate()
调用中触发。注入是发生的第一件事,这意味着mutate()
还没有足够的时间来设置across()
需要的数据屏蔽上下文,因此时机太晚了。
为了解决这个问题,必须消除注入上下文之间的重叠。这就是你通过将 !!!
移动到另一个函数中所做的。另一种方法是注入对 coalesce()
的调用,但这相当丑陋且很难理解:
aa |> mutate(c = !!quote(coalesce(!!!across(starts_with('a')))))
我更喜欢你的 coacross()
解决方案。
英文:
You've reached the obscure side of tidy eval programming :-/
The problem is that !!!
is evaluated very early by the first verb that happens to support injection operators:
-
In your first example, there isn't any injection in the
mutate()
call. Instead,!!!
is triggered at thecoalesce()
call insidecoacross()
, and so the timing is correct. -
In your second example,
!!!
is triggered at themutate()
call. Injection is the very first thing that happens, which means thatmutate()
hasn't had time yet to set up the data-masking context thatacross()
needs, and so the timing is too late.
To work around this the overlap between injection contexts must be removed. This is what you did by moving the !!!
in another function. An alternative is to inject a call to coalesce()
but that's rather ugly and very hard to understand:
aa |> mutate(c = !!quote(coalesce(!!!across(starts_with('a')))))
I prefer your coacross()
solution.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论