如何在R中获取变量的环境

Posted

技术标签:

【中文标题】如何在R中获取变量的环境【英文标题】:How to get environment of a variable in R 【发布时间】:2013-05-11 02:19:44 【问题描述】:

我想知道是否有任何方法可以获取已声明变量的环境。假设我已经向环境声明了一个变量,并希望使用该变量的环境来声明更多变量。类似 getEnv("variable")

【问题讨论】:

为什么需要这个?也许我们可以提出更好的解决方案。我会谨慎地像这样工作,创建一个包含它们之间关系的环境网络可能真的很难理解和调试。我只会使用一组函数,并通过输入参数传递他们需要的任何信息。 您可以使用find,但前提是环境是attached 到搜索路径。 我想让一些变量有一个特定的环境。作为检查,我想看看两个变量是否具有相同的环境。类似于我的 RUnit 测试套件的一部分。我只是想,既然我们可以选择在使用 assign 函数时提供环境,那么也应该有一些简单的方法来获取分配的环境,我会添加检查,仅此而已。没有什么关键任务。 这是一个非常有趣的问题,但我相信环境不是变量的属性;相反,环境包含附加的符号列表。但是如果有一个功能可以列出当前可用的所有环境,那就太好了。在内部,R 必须跟踪它,但我知道没有提供此信息的函数。 【参考方案1】:

您可以使用ls() 获取工作区中的所有对象,因此您可以检查其中哪些是环境:

envirs <- ls()[sapply(ls(), function(x) is.environment(get(x)))]

我需要在那里使用get(),因为ls() 返回对象的字符名称而不是对象本身。现在给定一个对象x,我们想要找到它存在于哪些环境中。我们需要做的就是遍历envirs 中的每个环境,并检查它们是否包含我们正在寻找的任何对象。类似于(检查变量x):

sapply(envirs, function(e) 'x' %in% ls(envir=get(e)))

这里有一个函数来完成这一切:

getEnv <- function(x) 
  xobj <- deparse(substitute(x))
  gobjects <- ls(envir=.GlobalEnv)
  envirs <- gobjects[sapply(gobjects, function(x) is.environment(get(x)))]
  envirs <- c('.GlobalEnv', envirs)
  xin <- sapply(envirs, function(e) xobj %in% ls(envir=get(e)))
  envirs[xin] 

这和我在函数之外所做的差不多。 gobjectsls() 读取,这一次显式检查全局环境 .GlobalEnv,因为它现在在一个函数中。

envirs 和以前一样,只是现在它也会检查.GlobalEnvxin 存储了找到 x 的环境的名称。行:

xobj <- deparse(substitute(x))

允许在不带引号的情况下测试对象,例如getEnv(x)getEnv('x')。不过,这是一个偏好问题,您可以将其更改为接受字符。


这里有一些测试。

x1 <- 1
getEnv(x1)
# ".GlobalEnv"

x2 <- 2.1
e2 <- new.env()
assign('x2', 2.2, e2)
getEnv(x2)
# ".GlobalEnv" "e2" 

e3 <- new.env()
assign('x3', 3, e3)
getEnv(x3)
# "e3"

这只检查在.GlobalEnv 中创建的环境。我敢肯定,如果需要,您可以研究如何扩展它以在更多环境中进行搜索。

我很惊讶没有一些内置功能。或者也许有,但我不知道。我以前从来没有真正需要做这样的事情,所以也许这并不奇怪。

【讨论】:

首先,我会将all=TRUE 添加到您的ls 电话中。然后我会递归地制作getEnv 搜索环境。但它仍然不检查未绑定到变量的环境,例如为闭包评估创建的环境。示例在控制台中运行:f &lt;- function(x) hidden &lt;- x; function()hidden &lt;&lt;- hidden+1; hidden ;g &lt;- f(0);as.list(environment(g)) 另外,列表可能有环境作为元素,可能有环境潜伏在任何对象的属性中等等。 @MadScone 感谢您的回答和其他所有人!甚至令我惊讶的是,没有内置功能。我最终决定不做那张支票,但再次感谢您的宝贵时间。【参考方案2】:

这个怎么样:

getEnvOf <- function(what, which=rev(sys.parents())) 
  for (frame in which)
    if (exists(what, frame=frame, inherits=FALSE)) 
      return(sys.frame(frame))
  return(NULL)

那么我们可以:

x <- 1
getEnvOf("x")
# <environment: R_GlobalEnv>

getEnvOf("y")
# NULL

f <- function() getEnvOf("x")
f()
# <environment: R_GlobalEnv>

g <- function()  x <- 2; getEnvOf("x") 
g()
# <environment: 0x114c26518>

【讨论】:

很好的功能回答了这个问题。除了问题的范围之外,似乎还有一些限制需要注意,例如。 G。 warning("oops");getEnvOf("last.warning") 导致NULLpryr::where("last.warning") 导致&lt;environment: base&gt;。您的函数确实在附加包的搜索路径中搜索,但在当前调用堆栈的框架中搜索(如前所述,问题中没有要求这样做,但其他用户应该知道这一点)。 效果很好!我在 return 语句中添加了“capture.output()”,只得到所需的字符串!【参考方案3】:

参考: http://adv-r.had.co.nz/Environments.html#env-basics

library(pryr)
x <- 5
where("x")
#> <environment: R_GlobalEnv>
where("mean")
#> <environment: base>

where 函数在上面的网站中有描述。它只查找变量出现的第一个环境,但可以轻松修改以查找所有环境。

【讨论】:

【参考方案4】:

您可以使用find,正如注释中已经建议的那样,在searchpath 中搜索对象的环境。如果您想在 Function Call Stack 中搜索,可以使用 exists 来查看 sys.frame's。

findFrame <- function(what) 
  n <- sys.nframe()-1
  Filter(Negate(is.null), lapply(n:0, function(i) 
    if(exists(what, sys.frame(i), inherits=FALSE)) sys.frame(i)))


x <- 0
f1 <- function() 
  x <- 1
  f2()

f2 <- function() 
  x <- 2
  tt  <- find("x")
  print(sapply(tt, as.environment))
  tt <- findFrame("x")
  print(tt)

a <- new.env(parent=emptyenv())
a$x <- 3
attach(a)
b <- new.env(parent=emptyenv())
b$x <- 4

find("x")
#[1] ".GlobalEnv" "a"

findFrame("x")
#[[1]]
#<environment: R_GlobalEnv>

f1()
#$.GlobalEnv
#<environment: R_GlobalEnv>
#
#$a
#<environment: 0x5576b0c7bb80>
#attr(,"name")
#[1] "a"
#
#[[1]]
#<environment: 0x5576af2fa1f8>
#
#[[2]]
#<environment: 0x5576aedcab20>
#
#[[3]]
#<environment: R_GlobalEnv>

f2()
#$.GlobalEnv
#<environment: R_GlobalEnv>
#
#$a
#<environment: 0x5576b0c7bb80>
#attr(,"name")
#[1] "a"
#
#[[1]]
#<environment: 0x5576b013bef0>
#
#[[2]]
#<environment: R_GlobalEnv>

【讨论】:

以上是关于如何在R中获取变量的环境的主要内容,如果未能解决你的问题,请参考以下文章

如何让 R 读取我的环境变量?

如何在 R 中从参数中获取其名称的函数中创建变量?

如何在 csproj 文件中获取环境变量?

如何在makefile中获取shell环境变量?

如何在 C# 中获取和设置环境变量?

如何在 Python 中获取 PATH 环境变量分隔符?