R 为什么Tidyeval报价在lamdas中失败?
下面是一个简单的例子,说明如何使用引号动态重命名TIBLE列R 为什么Tidyeval报价在lamdas中失败?,r,dplyr,tidyverse,tidyeval,R,Dplyr,Tidyverse,Tidyeval,下面是一个简单的例子,说明如何使用引号动态重命名TIBLE列 quoteExample = function() { new_name = quo("new_name_value"); tibble(old_name=list(1,2,3)) %>% rename( !! quo_name(new_name) := old_name) } quoteExample() 结果=TIBLE(新名称\u值=列表(1,2,3)) 下面是同一个简单的例子,但这
quoteExample = function() {
new_name = quo("new_name_value");
tibble(old_name=list(1,2,3)) %>%
rename( !! quo_name(new_name) := old_name)
}
quoteExample()
结果=TIBLE(新名称\u值=列表(1,2,3))
下面是同一个简单的例子,但这次是在一个lamda中
{function ()
new_name = quo("new_name_value");
tibble(old_name=list(1,2,3)) %>%
rename( !! quo_name(new_name) := old_name)
} ()
结果=信息查询(quo)中出错:未找到对象“新名称”
为什么引号在lamda中失败,但在命名函数中却失败?这种差异从何而来?我做错什么了吗
编辑:上述示例已由Akrun解决,但下面是另一个失败的示例,尽管已应用建议的解决方案:
df = tibble(data=list(tibble(old_name= c(1,2,3))))
df %>%
mutate(data = map(data, (function(d){
new_name = quo("new_value")
d %>% rename( !! quo_name(new_name) := old_name)
})))
结果:错误信息(quo):未找到对象“新名称”
这个失败是因为另一个问题吗 如果我们使用
()
或{}
使其自包含,它应该可以工作
(function() {
new_name = quo("new_name_value");
tibble(old_name=list(1,2,3)) %>%
rename( !! quo_name(new_name) := old_name)
})()
# A tibble: 3 x 1
# new_name_value
# <list>
#1 <dbl [1]>
#2 <dbl [1]>
#3 <dbl [1]>
(函数(){
新名称=quo(“新名称”值);
TIBLE(旧名称=列表(1,2,3))%>%
重命名(!!quo_名称(新名称):=旧名称)
})()
#一个tibble:3x1
#新的\u名称\u值
#
#1
#2
#3
如果匿名函数只包含一个表达式
会话,则不需要使用{}
,但如果它有多行表达式,则使用{}
换行。根据?主体
除了最简单的以外,所有的主体都是大括号表达式,即对{的调用:有关如何创建这样的调用,请参阅“示例”部分
如果我们使用
()
或{}
使其自包含,那么它应该可以工作
(function() {
new_name = quo("new_name_value");
tibble(old_name=list(1,2,3)) %>%
rename( !! quo_name(new_name) := old_name)
})()
# A tibble: 3 x 1
# new_name_value
# <list>
#1 <dbl [1]>
#2 <dbl [1]>
#3 <dbl [1]>
(函数(){
新名称=quo(“新名称”值);
TIBLE(旧名称=列表(1,2,3))%>%
重命名(!!quo_名称(新名称):=旧名称)
})()
#一个tibble:3x1
#新的\u名称\u值
#
#1
#2
#3
如果匿名函数只包含一个表达式
会话,则不需要使用{}
,但如果它有多行表达式,则使用{}
。根据正文
除了最简单的以外,所有的主体都是大括号表达式,即对{的调用:有关如何创建这样的调用,请参阅“示例”部分
这与问题基本相同。主要原因是在创建匿名函数环境之前,
!!
运算符强制立即计算其参数尝试查找相对于整个表达式(即整个mutate(…)
表达式)的new\u name
定义。由于new\u name
是在表达式本身中定义的,因此最终会出现循环依赖关系,导致“未找到对象”错误
你有三个选择
1) 将lambda拉出到一个独立函数中,以确保首先创建其环境,从而在!!
运算符强制其计算之前正确初始化该环境中的所有变量:
f <- function(d) {
new_name = sym("new_value")
d %>% rename(!!new_name := old_name)
}
df %>% mutate(data = map(data, f))
3) 重写表达式,使其不使用!!
运算符来计算尚未初始化的变量(本例中为new\u name
):
旁注:您会注意到我用
sym()
替换了您的quo()
调用。函数quo()
捕获一个表达式及其环境。由于字符串文字“new\u value”
将始终计算为相同的值,不需要在其环境中进行标记。通常,将列名捕获为符号的正确动词是sym()
这与问题基本相同。主要原因是在创建匿名函数环境之前,!!
运算符强制立即计算其参数。。在您的情况下,!!quo_名称(新名称)
尝试查找相对于整个表达式(即整个mutate(…)
表达式)的new\u name
定义。由于new\u name
是在表达式本身中定义的,因此最终会出现循环依赖关系,导致“未找到对象”错误
你有三个选择
1) 将lambda拉出到一个独立函数中,以确保首先创建其环境,从而在!!
运算符强制其计算之前正确初始化该环境中的所有变量:
f <- function(d) {
new_name = sym("new_value")
d %>% rename(!!new_name := old_name)
}
df %>% mutate(data = map(data, f))
3) 重写表达式,使其不使用!!
运算符来计算尚未初始化的变量(本例中为new\u name
):
旁注:您会注意到我用
sym()
替换了您的quo()
调用。函数quo()
捕获一个表达式及其环境。由于字符串文字“new\u value”
将始终计算为相同的值,不需要在其环境中进行标记。通常,将列名捕获为符号的正确动词是sym()
@akrun我不确定你的意思,你能详细解释一下吗?@akrun谢谢,我纠正了错误,不幸的是这并不能解决问题。@akrun是的,“name”的类型是字符,运行mutate时包含值“new\u name\u value”。并因此复制其他示例。取消列出或强制转换字符“name”没有任何区别。您可以使用rename\u at
t1%>%mutate(new=map2(name,data,~{new\u name%rename\u at(vars(old\u name),~new\u name)})
@akrun我已经简化了示例,以避免出现您建议的参数传递问题。@akrun我不确定您的意思,您能详细解释一下吗?@akrun谢谢,我纠正了错误,不幸的是这并不能解决问题。@akrun是的,“name”的类型是字符,运行mutate时包含值“new\u name\u value”。并因此复制其他示例。取消列出或强制转换“名称”到