R:向量元素的全局赋值仅在函数内部起作用 [英] R: Global assignment of vector element works only inside a function

查看:108
本文介绍了R:向量元素的全局赋值仅在函数内部起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在做一个有一些全局任务的项目,但是遇到了一些奇怪的事情.我希望有人可以帮助我.

I'm working on a project where there are some global assignments, and I ran into something sort of odd. I was hoping someone could help me with it.

我写了这个玩具示例来演示这个问题:

I wrote this toy example to demonstrate the problem:

x <-  1:3 ; x <-  c(1, 2, 5) # this works fine
x <-  1:3 ; x[3] <- 5        # this works fine

x <<- 1:3 ; x <<- c(1, 2, 5) # this works fine
x <<- 1:3 ; x[3] <<- 5       # this does not work
# Error in x[3] <<- 5 : object 'x' not found

same.thing.but.in.a.function = function() {
  x <<- 1:3
  x[3] <<- 5
}
same.thing.but.in.a.function(); x
# works just fine

因此,似乎不可能使用全局赋值来更改矢量的一部分-除非该赋值包含在函数中.谁能解释为什么会这样?

So, it seems it's not possible to change part of a vector using a global assignment -- unless that assignment is contained within a function. Can anyone explain why this is the case?

推荐答案

我发现了问题所在.

基本上,在<<-的这种表示形式(更准确地称为超级分配运算符"而不是全局分配运算符")中,实际上在尝试访问变量时会跳过对全局环境的检查.

Basically, in this manifestation of <<- (which is more accurately called the "superassignment operator" rather than the "global assignment operator"), it actually skips checking the global environment when trying to access the variable.

R语言定义的第19页上,声明以下内容:

On page 19 of R Language Definition, it states the following:

x <<- data.frame(0, 0, 0) # (I added this so the code can be run)
names(x)[3] <<- "Three"

等同于

x <<- data.frame(0, 0, 0) # (I added this so the code can be run)
`*tmp*` <<- get(x, envir=parent.env(), inherits=TRUE)
names(`*tmp*`)[3] <- "Three"
x <<- `*tmp*`
rm(`*tmp*`)

当我尝试运行这四行代码时,它引发了错误-parent.env需要一个参数且没有默认值.我只能假设文档是在parent.env()包含其第一个参数的默认值的时间编写的.但是我可以放心地猜测默认值是environment(),它将返回当前环境.然后它再次引发错误-x需要用引号引起来.所以我也解决了.现在,当我运行第一行时,它会引发与我最初遇到的错误消息相同的消息,但会提供更多详细信息:

When I tried to run those four lines, it threw an error -- parent.env requires an argument and has no default. I can only assume that the documentation was written at a time when parent.env() contained a default value for its first argument. But I can safely guess that the default would have been environment() which returns the current environment. It then throws an error again -- x needs to be in quotes. So I fixed that too. Now, when I run the first line, it throws the same error message as I encountered originally, but with more detail:

# Error in get("x", envir = parent.env(environment()), inherits = TRUE) :
#   object 'x' not found

这很有道理-environment()本身返回.GlobalEnv,因此parent.env(.GlobalEnv)完全错过了全局环境,而是返回了最近加载的软件包环境.然后,由于inherits设置为TRUE,所以get()函数会不断升级,在最终到达空环境之前搜索每个已加载的程序包环境,此时仍未找到.因此就是错误.

This makes sense -- environment() itself returns .GlobalEnv, so parent.env(.GlobalEnv) misses out on the global environment entirely, instead returning the most recently loaded package environment. Then, since inherits is set to TRUE, the get() function keeps going up the levels, searching through each of the loaded package environments before eventually reaching the empty environment, and at that point it has still not found x. Thus the error.

由于只要您在本地环境中开始,parent.env(environment())都将返回.GlobalEnv(或其下的另一个环境),所以当在本地环境中运行相同的行时,不会发生相同的问题:*

Since parent.env(environment()) will return .GlobalEnv (or another environment below it) as long as you start inside a local environment, this same problem does not occur when the same lines are run from inside a local environment:*

local({
  x <<- data.frame(0, 0, 0) # (I added this so the code can be run)
  `tmp` <<- get("x", envir=parent.env(environment()), inherits=TRUE)
  names(`tmp`)[3] <- "Three"
  x <<- `tmp`
  rm(`tmp`)
})
x
#   X0 X0.1 Three
# 1  0    0     0

# so, it works properly

相反,通常使用<<-时,在幕后不会出现任何额外的子集代码,并且它首先尝试在移动之前在当前环境(可能是全局环境)中访问该值.向上.因此,在那种情况下,它不会遇到跳过全局环境的问题.

In contrast, when <<- is used in general, there is no extra subsetting code that occurs behind the scenes, and it first attempts to access the value in the current environment (which might be the global environment), before moving upwards. So in that situation, it doesn't run into the problem where it skips the global environment.

*我不得不将变量从*tmp*更改为tmp,因为代码中的幕后操作之一使用了*tmp*变量,然后将其删除,因此*tmp*消失了在第3行的中间,因此当我尝试访问它时会引发错误.

* I had to change the variable from *tmp* to tmp because one of the behind-the-scenes operations in the code uses the *tmp* variable and then removes it, so *tmp* disappears in the middle of line 3 and so it throws an error when I then try to access it.

这篇关于R:向量元素的全局赋值仅在函数内部起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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