我试图通过几个函数传递变量,并且在最终函数上我希望得到原始变量的名称。但似乎R中的替代功能只能在" local"环境,或只是一个级别。好吧,让我用代码解释一下:
fun1 <- function (some_variable) {deparse(substitute(some_variable)}
fun2 <- function (var_pass) { fun1 (var_pass) }
my_var <- c(1,2) # I want to get 'my_var' in the end
fun2 (my_var) # > "var_pass"
好吧,好像我们打印的变量名只传递给fun1。替代品的文档告诉我们,我们可以使用env参数来指定我们可以看到的位置。但是通过传递 .Global 或 .BaseNamespaceEnv 作为替代参数我得到了更奇怪的结果 - &#34; some_variable&#34;
我相信使用env参数可以回答这个问题,所以,请你解释一下它是如何工作的,我怎样才能得到我需要的东西。提前谢谢!
答案 0 :(得分:12)
我建议您考虑将可选名称值传递给这些函数。我这样说是因为看起来你真的想在最终结果中使用这个名字作为标签。所以变量本身并不像其名称那么重要。你可以做到
fun1 <- function (some_variable, name=deparse(substitute(some_variable))) {
name
}
fun2 <- function (var_pass, name=deparse(substitute(var_pass))) {
fun1 (var_pass, name)
}
my_var <- c(1,2)
fun2(my_var)
# [1] "my_var"
fun1(my_var)
# [1] "my_var"
这样一来,如果您最终得到一些奇怪的变量名称以及为结果提供更好的名称,那么您至少可以选择。默认情况下,它可以执行您想要的操作而无需使用name参数。
答案 1 :(得分:0)
一个黑客,可能不是最好的方式:
fun2 <- function (var_pass) { fun1 (deparse(substitute(var_pass))) }
fun1 <- function (some_variable) {(some_variable))}
fun2(my_var)
# "my_var"
你可以运行get
。但正如Paul H所说,有更好的方法来跟踪变量。
答案 2 :(得分:0)
我想建议的另一种方法是使用rlang::enexpr
。
主要优点是我们不需要在参数中携带原始变量名。缺点是我们必须处理使用起来有些棘手的表达式。
> fun1 <- function (some_variable) {
message("Entering fun1")
rlang::enexpr(some_variable)
}
> fun2 <- function (var_pass) {
message("Entering fun2")
eval(parse(text=paste0("fun1(", rlang::enexpr(var_pass), ")")))
}
> my_var <- c(1, 2)
> fun1(my_var)
#Entering fun1
my_var
> fun2(my_var)
#Entering fun2
#Entering fun1
my_var
这里的技巧是我们必须评估fun2
中的参数名称,并以fun1
的形式构建对character
的调用。如果我们仅用fun1
调用enexpr(var_pass)
,我们将失去fun2
变量名的概念,因为enexpr(var_pass)
永远不会在fun2
中求值:
> bad_fun2 <- function (var_pass) {
message("Entering bad fun2")
fun1(rlang::enexpr(var_pass))
}
> bad_fun2(my_var)
#Entering bad fun2
#Entering fun1
rlang::enexpr(var_pass)
最重要的是,请注意fun1
和fun2
都不返回变量名称作为字符向量。返回的对象属于name
类(当然可以强制为character
)。
好的一面是,您可以直接在其上使用eval
。
> ret <- fun2(my_var)
#Entering fun2
#Entering fun1
> as.character(ret)
[1] "my_var"
> class(ret)
[1] "name"
> eval(ret)
[1] 1 2