gpt4 book ai didi

r - 匿名函数中的rlang::sym

转载 作者:行者123 更新时间:2023-12-03 22:35:19 25 4
gpt4 key购买 nike

我最近注意到rlang::sym在匿名函数中似乎不起作用,我也不明白为什么。这是一个例子,非常笨拙和丑陋,但我认为它说明了这一点

require(tidyverse)
data <- tibble(x1 = letters[1:3],
x2 = letters[4:6],
val = 1:3)

get_it <- function(a, b){
data %>%
mutate(y1 = !!rlang::sym(a)) %>%
mutate(y2 = !!rlang::sym(b)) %>%
select(y1, y2, val)
}
get_it("x1", "x2")


这定义了一些玩具数据和一个(可怕的)函数,该函数实质上根据列名重命名列。现在,我可以对a和b的不同组合执行相同的操作:

d <- tibble(x = c("x1", "x2"),
y = c("x2", "x1"))
d %>% mutate(tmp = map2(x, y, get_it))


但是,如果我尝试使用匿名函数执行完全相同的操作,那么它将不起作用:

d %>% mutate(tmp = map2(x, y, function(a, b){
data %>%
mutate(y1 = !!rlang::sym(a)) %>%
mutate(y2 = !!rlang::sym(b)) %>%
select(y1, y2, val)
}))


即使 object 'a' not found的功能完全相同(在这里是匿名的),此操作也会失败。谁能解释为什么?

最佳答案

问题不是匿名函数,而是!!的运算符优先级。 !!的帮助页面指出:


!!运算符取消引用其参数。立即在周围环境中对其进行评估。


这意味着当您编写一个复杂的NSE表达式(例如select内的mutate)时,取消引用将在整个表达式的环境中发生。如@lionel所指出的,然后取消引用优先于其他事情,例如创建匿名函数环境。

在您的情况下,相对于外部!!取消了mutate()的引用,然后尝试在x1而不是d内查找列data。有两种可能的解决方案:

1)将涉及!!的表达式放入独立函数中(如您在问题中所做的那样):

res1 <- d %>% mutate(tmp = map2(x, y, get_it))


2)将 !!替换为 eval以延迟表达式求值:

res2 <- d %>% mutate(tmp = map2(x, y, function(a, b){
data %>%
mutate(y1 = eval(rlang::sym(a))) %>%
mutate(y2 = eval(rlang::sym(b))) %>%
select(y1, y2, val)
}))

identical(res1, res2) #TRUE

关于r - 匿名函数中的rlang::sym,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51902438/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com