save(),意外行为
Posted
技术标签:
【中文标题】save(),意外行为【英文标题】:save(), unexpected behavior 【发布时间】:2014-07-22 17:12:18 【问题描述】:我正在尝试通过 save() 保存函数调用中的变量
f <- function(x)
r <- x - g(x)
r
g <- function(y)
r <- y * h(y)
r
h <- function(z)
save(list = ls(all = TRUE), file = "hello.RData", envir = parent.frame())
r <- log(z)
if (r < 10)
r^2
else r^3
然而,这会返回错误“object z not found”,即使根据文档 parent.frame() 是 envir 的标准值。
save(list = ls(all = TRUE), file = "hello.RData", envir = sys.frame())
也不行
save(list = ls(all = TRUE), file = "hello.RData")
这行得通。但是,如果不是文档中给出的标准值,envir 实际上是什么对我来说有点神秘。
错误的原因是什么,为什么父框架是要在save()中查看的标准环境?
【问题讨论】:
虽然我知道这里正在进行范围界定,但您的函数h
在返回正确值的意义上工作得很好。您应该明确指出,将内部变量保存到您的 .rdata
文件是行不通的。
【参考方案1】:
需要注意的重要一点是,函数的默认值在哪里评估和你传入的值在哪里评估是不同的。考虑
ff<-function(a, b=a+2) print(b)
ff(2);
# [1] 4
ff(2, a+2);
# Error in print(b) : object 'a' not found
尽管b
的“默认”是a+2
,但我们不能只传入a+2
,因为它需要在不同的上下文中进行评估。
这是另一个例子
gg<-function(a)
ff(2, match.call());
ff<-function(a, b=match.call())
print(b)
ff(2);
# ff(a = 2)
gg(2)
# gg(a = 2);
尽管gg
将相同的“默认值”传递给ff
,但我们得到了不同的行为。
save(..., envir=parent.frame())
就是这样。当您在h()
中调用该函数时,您将从调用h()
的位置获取帧,但如果您未指定环境,当save
调用parent.frame()
时,save
将获得调用的帧save()
被调用。如果你想明确地将 current 环境传递给save()
,你可以这样做
save(list = ls(all = TRUE), file = "hello.RData", envir=environment())
但这与根本不指定envir=
参数的作用基本相同。
所以文档是正确的,只是行为会有所不同,具体取决于实际调用parent.frame()
的人。
【讨论】:
正如 R-inferno 中所讨论的。【参考方案2】:这个问题与范围界定有关。有关范围的深入描述,请查看这篇文章http://adv-r.had.co.nz/Functions.html#lexical-scoping
首先,通过指定 envir=parent.frame() 来选择全局环境。这是因为您的函数未在另一个函数或对象中定义。例如,查看我在下面定义的两个不同 h 函数中打印 parent.frame 之间的区别。
!> h <- function(z)
+ print(parent.frame())
+
>
>
> h(10)
<environment: R_GlobalEnv>
>
> h <- function(z)
+ b <- function()
+ print(parent.frame())
+ b()
+
>
> h()
<environment: 0x10f06b3c0>
我相信你要么想将你的函数相互嵌套(如上所示的函数 h 和 b),要么声明一个“全局变量”。这是由
<<-
命令
例如:
> h <- function(z)
+ r <<- log(z)
+ if (r < 10)
+ r <<- r^2
+ else r<<- r^3
+
> h(1)
> r
[1] 0
> h(10)
> r
[1] 5.301898
> h(10000)
!> r
[1] 84.83037
【讨论】:
以上是关于save(),意外行为的主要内容,如果未能解决你的问题,请参考以下文章