R中的环境,应用和获取 [英] Environments in R, mapply and get

查看:112
本文介绍了R中的环境,应用和获取的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在全球环境中让 x <-2

  x <-2 
x
[1] 2

a 是一个在本地定义另一个 x 并使用 get

  a <-function(){
x <-1
get(x)



$ b

这个函数正确地得到 x 来自当地的环境:

  a()
[1] 1

现在让我们定义一个函数 b ,如下所示,它使用 mapply with get

  b < -  <函数(){
x <-1
mapply(get,x)
}

如果我调用 b ,看起来 mapply 会使得到不首先搜索功能环境。相反,它试图直接从全局环境中获取 x ,并且如果未在全局环境中定义 x (b)

  b()
x
2
rm(x)
b()
错误in(function(x,pos = -1L,envir = as.environment(pos),mode =any,:
object'x'not found

解决方案是显式定义 envir = environment()
$ p $ c <-function(){
x <-1
mapply(get ,x,MoreArgs = list(envir = environment()))
}

c()
x
1

但是我想知道这里究竟发生了什么。 mapply 是干什么的? (为什么?这是预期的行为?)这是其他R函数常见的陷阱吗?

解决方案

问题是 get 查看其从中调用的环境,但在这里我们传递了中的本地环境获取 mapply ,然后调用获得 > mapply 。如果在 mapply 本地环境中未找到 x ,那么它会查找该环境的父环境,即 environment(mapply)(这是在基本命名空间环境中定义了mapply的词法环境);如果它不在那里,它会查看它的父级,即全局环境,即你的R工作区。



这是因为R使用了词法范围界定,与动态范围界定相反



我们可以通过获取一个存在于 mapply 中的变量来显示它。

  x < -  2 
b2 < - function(){
x <-1
mapply(get,USE.NAMES)
}
b2()#它在mapply中找到USE.NAMES
## USE.NAMES
## TRUE

除了涉及 MoreArgs 这个问题也适用,因为它会导致搜索在找不到 mapply 之后查看 b 中的本地环境。 (这只是为了说明发生了什么,在实际操作中我们更喜欢问题中显示的解决方法。)

  x <  -  2 
b3< -function(){
x< -1
environment(mapply)< - environment()
mapply(get,x)

b3()
## 1

添加扩展说明。另请注意,我们可以查看如下环境链:

 >调试(获取)
> b()
调试:(function(x,pos = -1L,envir = as.environment(pos),mode =any,
inherits = TRUE)
.Internal get(x,envir,mode,inherits)))(dots [[1L]] [[1L]])
debug:.Internal(get(x,envir,mode,inherits))
浏览[2]> envir
< environment:0x0000000021ada818>
浏览[2]> ls(envir)###这表明envir是mapply中的本地环境
[1]dotsFUNMoreArgsSIMPLIFYUSE.NAMES
浏览[2]> ; parent.env(envir)### envir的父节点是基本命名空间env
< environment:namespace:base>
浏览[2]> parent.env(parent.env(envir))###和envir的祖父母是全局环境
< environment:R_GlobalEnv>

因此,可能遵循的环境祖先就是这样(箭头指向父项):

  mapply内的本地环境 - >环境(mapply) - > .GlobalEnv 

其中环境(mapply)等于 asNamespace(base),即基本命名空间环境。


Let x<-2 in the global env:

x <-2 
x
[1] 2

Let a be a function that defines another x locally and uses get:

a<-function(){
  x<-1
  get("x")
}

This function correctly gets x from the local enviroment:

a()
[1] 1

Now let's define a function b as below, that uses mapply with get:

b<-function(){
  x<-1
  mapply(get,"x")
}

If I call b, it seems that mapply makes get not search the function environment first. Instead, it tries to get x directly form the global enviroment, and if x is not defined in the global env, it gives an error message:

b()
x 
2 
rm(x)
b()
Error in (function (x, pos = -1L, envir = as.environment(pos), mode = "any",  : 
  object 'x' not found 

The solution to this is to explicitly define envir=environment().

c<-function(){
  x<-1
  mapply(get,"x", MoreArgs = list(envir=environment()))
}

c()
x 
1 

But I would like to know what exactly is going on here. What is mapplydoing? (And why? is this the expected behavior?) Is this "pitfall" common in other R functions?

解决方案

The problem is that get looks into the envivornment that its called from but here we are passing get to mapply and then calling get from the local environment within mapply. If x is not found within the mapply local environment then it looks the into the parent environment of that, i.e. into environment(mapply) (which is the lexical environment that mapply was defined in which is the base namespace environment); if it is not there either, it looks into the parent of that, which is the global environment, i.e. your R workspace.

This is because R uses lexical scoping, as opposed to dynamic scoping.

We can show this by getting a variable that exists within mapply.

 x <- 2
 b2<-function(){
   x<-1
   mapply(get, "USE.NAMES")
 }
 b2() # it finds USE.NAMES in mapply
 ## USE.NAMES 
 ##     TRUE 

In addition to the workaround involving MoreArgs shown in the question this also works since it causes the search to look into the local environment within b after failing to find it mapply. (This is just for illustrating what is going on and in actual practice we would prefer the workaround shown in the question.)

x <- 2
b3 <-function(){
   x<-1
   environment(mapply) <- environment()
   mapply(get, "x")
}
b3()
## 1

ADDED Expanded explanation. Also note that we can view the chain of environments like this:

> debug(get)
> b()
debugging in: (function (x, pos = -1L, envir = as.environment(pos), mode = "any", 
    inherits = TRUE) 
.Internal(get(x, envir, mode, inherits)))(dots[[1L]][[1L]])
debug: .Internal(get(x, envir, mode, inherits))
Browse[2]> envir
<environment: 0x0000000021ada818>
Browse[2]> ls(envir) ### this shows that envir is the local env in mapply
[1] "dots"      "FUN"       "MoreArgs"  "SIMPLIFY"  "USE.NAMES"
Browse[2]> parent.env(envir) ### the parent of envir is the base namespace env
<environment: namespace:base>
Browse[2]> parent.env(parent.env(envir)) ### and grandparent of envir is the global env
<environment: R_GlobalEnv>

Thus, the ancestory of environments potentially followed is this (where arrow points to parent):

local environment within mapply --> environment(mapply) --> .GlobalEnv

where environment(mapply) equals asNamespace("base"), the base namespace environment.

这篇关于R中的环境,应用和获取的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆