R中的全局变量和局部变量
Posted
技术标签:
【中文标题】R中的全局变量和局部变量【英文标题】:Global and local variables in R 【发布时间】:2012-06-09 20:57:20 【问题描述】:我是 R 的新手,我对 R 中局部变量和全局变量的使用感到很困惑。
我在网上看到一些帖子说如果我使用=
或<-
我将在当前环境中分配变量,而使用<<-
我可以在函数内部访问全局变量。
但是,我记得在 C++ 中,每当您在括号 内声明一个变量时,就会出现局部变量,所以我想知道这对于 R 是否相同?还是只是为了R中的函数,我们才有了局部变量的概念。
我做了一个小实验,似乎表明只有括号是不够的,我有什么问题吗?
x=matrix(1:10,2,5)
print(x[2,2])
[1] 4
【问题讨论】:
除了这些答案之外还要运行一些代码:globalenv(); globalenv() %>% parent.env; globalenv() %>% parent.env %>% parent.env
, ...
@isomorphismes, Error: could not find function "%>%"
。这是另一种形式的任务吗?
R-help 上的相关帖子:What does the "<<-" operator mean?.
@AaronMcDaid 嗨,很抱歉没有尽快回复!那是来自require(magrittr)
。这是一种在右侧 (x | f1 | f2 | f3
) 而非左侧 (f3( f2( f1( x ) ) )
) 应用函数的方式。
【参考方案1】:
在函数内部声明的变量是该函数的局部变量。例如:
foo <- function()
bar <- 1
foo()
bar
给出以下错误:Error: object 'bar' not found
。
如果你想让bar
成为一个全局变量,你应该这样做:
foo <- function()
bar <<- 1
foo()
bar
在这种情况下,bar
可以从函数外部访问。
但是,与 C、C++ 或许多其他语言不同,括号不能确定变量的范围。比如下面的代码sn-p:
if (x > 10)
y <- 0
else
y <- 1
y
在if-else
语句之后仍然可以访问。
正如您所说,您还可以创建嵌套环境。您可以查看这两个链接以了解如何使用它们:
-
http://stat.ethz.ch/R-manual/R-devel/library/base/html/environment.html
http://stat.ethz.ch/R-manual/R-devel/library/base/html/get.html
这里有一个小例子:
test.env <- new.env()
assign('var', 100, envir=test.env)
# or simply
test.env$var <- 100
get('var') # var cannot be found since it is not defined in this environment
get('var', envir=test.env) # now it can be found
【讨论】:
【参考方案2】:<-
在当前环境下赋值。
当你在一个函数中时,R 会为你创建一个新环境。默认情况下,它包含创建它的环境中的所有内容,因此您也可以使用这些变量,但您创建的任何新内容都不会写入全局环境。
在大多数情况下,<<-
将分配给已经在全局环境中的变量,或者在全局环境中创建一个变量,即使您在函数内部也是如此。然而,它并不像那样简单。它的作用是检查父环境以查找具有感兴趣名称的变量。如果它在您的父环境中找不到它,它会转到父环境的父环境(在创建函数时)并在那里查找。它继续向上到全局环境,如果在全局环境中找不到它,它将在全局环境中分配变量。
这可能说明正在发生的事情。
bar <- "global"
foo <- function()
bar <- "in foo"
baz <- function()
bar <- "in baz - before <<-"
bar <<- "in baz - after <<-"
print(bar)
print(bar)
baz()
print(bar)
> bar
[1] "global"
> foo()
[1] "in foo"
[1] "in baz - before <<-"
[1] "in baz - after <<-"
> bar
[1] "global"
我们第一次打印 bar 我们还没有调用 foo
所以它应该仍然是全局的 - 这是有道理的。我们第二次在调用baz
之前打印它在foo
的内部,所以“in foo”的值是有意义的。下面是我们看到<<-
实际在做什么的地方。打印的下一个值是“in baz - <<- 之后。这是因为<<-
不查看当前环境(除非您在全局环境中,在这种情况下<<-
的行为类似于<-
)。所以在baz
内部,bar 的值保持为“in baz - before baz,foo
内部的 bar 副本就会更改为“in baz”,但我们可以看到全局 bar
没有改变。这是因为foo
内部定义的bar
的副本在我们创建baz
时位于父环境中,因此这是<<-
看到的bar
的第一个副本,因此它分配给它的副本.所以<<-
不只是直接分配给全局环境。
<<-
很棘手,如果可以避免的话,我不建议使用它。如果您真的想分配给全局环境,您可以使用 assign 函数并明确告诉它您要全局分配。
现在我将<<-
更改为assign 语句,我们可以看到它有什么效果:
bar <- "global"
foo <- function()
bar <- "in foo"
baz <- function()
assign("bar", "in baz", envir = .GlobalEnv)
print(bar)
baz()
print(bar)
bar
#[1] "global"
foo()
#[1] "in foo"
#[1] "in foo"
bar
#[1] "in baz"
所以我们两次在foo
内打印 bar,即使在调用baz
之后,值也是“in foo”。这是因为 assign
甚至从未考虑过 foo 内部的 bar
的副本,因为我们告诉它确切的位置。但是,这一次全局环境中 bar 的值发生了变化,因为我们在那里显式分配了。
现在您还询问了创建局部变量的问题,您也可以很容易地做到这一点,而无需创建函数……我们只需要使用 local
函数。
bar <- "global"
# local will create a new environment for us to play in
local(
bar <- "local"
print(bar)
)
#[1] "local"
bar
#[1] "global"
【讨论】:
我可以配置一个函数,让它里面的环境和外面一样吗?这意味着使用 是的,但这是一个糟糕的主意。我不会帮你,因为那太糟糕了。最好返回结果并让用户决定如何使用它们。【参考方案3】:更多类似的内容
attrs <-
attrs.a <- 1
f <- function(d)
attrs.a <- d
f(20)
print(attrs.a)
将打印“1”
attrs <-
attrs.a <- 1
f <- function(d)
attrs.a <<- d
f(20)
print(attrs.a)
将打印“20”
【讨论】:
以上是关于R中的全局变量和局部变量的主要内容,如果未能解决你的问题,请参考以下文章