【问题标题】:How to get name of variable in R (substitute)?如何在 R(替代)中获取变量的名称?
【发布时间】:2014-06-19 15:05:38
【问题描述】:

我试图通过几个函数传递变量,并且在最终函数上我想获取原始变量的名称。但似乎 R 中的替代函数仅在“本地”环境中查看,或者仅在上一级。好吧,我用代码解释一下:

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 作为替代的参数,我得到了更奇怪的结果 - “some_variable”

我相信答案是在这个函数中使用 env 参数,所以,你能解释一下它是如何工作的,我怎样才能得到我需要的东西。提前致谢!

【问题讨论】:

  • 很确定“The R-Inferno”涉及到这一点。顺便说一句,我假设您打算用var_passfun2 内调用fun1
  • 哦,谢谢!是的,我的意思是 fun1(var_pass)。
  • 为什么首先需要这个名字。可能有一个更好、更简单的替代方案。
  • 好吧,我为 data.frame 做了很多计算,但最后我想访问列表 (my_list$my_var),获取一些与数据帧。可能有一些方法可以做到,我实际上做了我需要的,但它真的很乱。我将变量的名称作为附加列,但是对于大数据集,它确实会减慢进程
  • 如果您需要函数内部的数据,只需将其作为输入参数传递。同样,如果您在函数外部需要函数内部的任何内容,请使用 return 参数。这符合您的需求吗?

标签: r variables substitution


【解决方案1】:

我建议您考虑将可选名称值传递给这些函数。我这样说是因为您似乎真的想将名称用作最终结果的标签;所以真正重要的不是变量本身,而是它的名称。你可以这样做

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 参数。

【讨论】:

  • 这个很有趣! )) 但我认为 R 本身的问题。我什至会在 init() 步骤中添加名称参数,但正如我已经说过的,这不是使用 data.frames 的舒适方式
  • 我不理解您的评论@EvilAnton。我不确定init() 步骤是什么,或者这与data.frames 有什么具体关系。如果您想使用 name 从 data.frame 中提取列,如果 name 中的值与列名之一完全匹配,则可以使用 df[, name]
  • 我的意思是初始化步骤。当您将所有数据加载到工作区时。但实际上,你提出了一个很好的观点。如果要重命名它应该工作的一些列名。
【解决方案2】:

一个技巧,可能不是最好的方法:

fun2 <- function (var_pass) { fun1 (deparse(substitute(var_pass))) }

fun1 <- function (some_variable) {(some_variable))}

fun2(my_var)
# "my_var"

你可以在上面运行get。但正如 Paul H 所建议的,有更好的方法来跟踪变量。

【讨论】:

  • 如果有人能引导我去哪里寻找更好的方法,我将不胜感激:)
  • 好吧,我看到的一种实现我需要的方法是始终通过函数传递 char,然后只使用 get()。但这对我来说并不好看,至少从编程架构的方式来看。
【解决方案3】:

我想建议的另一种方法是使用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。如果我们简单地用enexpr(var_pass) 调用fun1,我们将失去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)

除此之外,请注意fun1fun2 都不会将变量名称作为字符向量返回。返回的对象属于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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-12
    • 2012-02-11
    • 1970-01-01
    相关资源
    最近更新 更多