R:向量元素的全局分配仅在函数内部有效

标签 r global-variables variable-assignment environment

我正在从事一个项目,其中有一些全局任务,我遇到了一些奇怪的事情。我希望有人能帮助我。

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

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

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

最佳答案

我发现了问题。

基本上,在<<-的这种表现形式中(更准确地称为“ super 赋值运算符”而不是“全局赋值运算符”),它实际上在尝试访问变量时跳过检查全局环境。

R Language Definition 的第 19 页上,它指出以下内容:

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需要用引号引起来。所以我也解决了这个问题。现在,当我运行第一行时,它会抛出与我最初遇到的相同的错误消息,但包含更多详细信息:

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

这是有道理的 -- environment()本身返回 .GlobalEnv ,所以parent.env(.GlobalEnv)完全错过全局环境,而是返回最近加载的包环境。然后,从inherits开始设置为TRUEget()函数不断向上,搜索每个加载的包环境,最终到达空环境,此时它仍然没有找到 x 。因此出现错误。

parent.env(environment())将返回.GlobalEnv (或其下面的另一个环境)只要您在本地环境中启动,当从本地环境内部运行相同的行时,就不会出现同样的问题:*

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

相反,当 <<-通常使用,在幕后没有发生额外的子集代码,并且它首先尝试访问当前环境(可能是全局环境)中的值,然后再向上移动。因此在这种情况下,它不会遇到跳过全局环境的问题。

* 我必须将变量从 *tmp* 更改为至tmp因为代码中的幕后操作之一使用了*tmp*变量,然后删除它,所以 *tmp*在第 3 行中间消失,因此当我尝试访问它时它会抛出错误。

关于R:向量元素的全局分配仅在函数内部有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44983596/

相关文章:

r - 在 R 中,将一个向量的切割(分割)应用于另一个向量

excel - 如何在 Excel VBA 中声明全局变量以在整个工作簿中可见

C 通过取消引用或地址运算符分配指针

c - 读取文本文件并比较每一行

c++ - 为什么 const char INITIAL ='G' 不是赋值语句?

r - 在 Hortonworks Sandbox hadoop 2.3 上安装 R

r - 具有自定义 bin 边缘的 ggplot2 密度直方图

r - ggplot : gradient fill high and low points

python - 使用同名的局部和全局变量了解输出

Vue 中 CSS 变量的使用