如果将对象x
传递给修改它的函数f
,R将在x
的环境中创建f
的修改后的本地副本,而不是更改原始对象(由于复制更改原则)。但是,我有一种情况x
非常大,一旦传递到f
就不需要,所以我想避免一次x
f
的原始副本存储} 叫做。有没有一种聪明的方法来实现这一目标?
f
是一个未知的函数,由一个可能不是很聪明的用户提供。
我到目前为止所做的最好的事情是将x
包裹在一个函数forget
中,该函数对名为x
的{{1}}进行新的本地引用,删除原始引用。工作区,然后传递新的引用。问题在于我不确定它是否达到了我想要的效果,它只适用于y
,这在我目前的案例中是一个交易破坏者。
globalenv()
以下是调用上述函数的示例。
forget <- function(x){
y <- x
# x and y now refers to the same object, which has not yet been copied
print(tracemem(y))
rm(list=deparse(substitute(x)), envir=globalenv())
# The outside reference is now removed so modifying `y`
# should no longer result in a copy (other than the
# intermediate copy produced in the assigment)
y
}
f <- function(x){
print(tracemem(x))
x[2] <- 9000.1
x
}
我正在做我希望自己做的事情吗?有更好的方法吗?
答案 0 :(得分:5)
(1)环境您可以使用以下环境:
e <- new.env()
e$x <- 1:3
f <- function(e) with(e, x <- x + 1)
f(e)
e$x
(2)引用类或自引用类自动使用环境后使用:
E <- setRefClass("E", fields = "x",
methods = list(
f = function() x <<- x + 1
)
)
e <- E$new(x = 1:3)
e$f()
e$x
(3)原型对象也使用环境:
library(proto)
p <- proto(x = 1:3, f = function(.) with(., x <- x + 1))
p$f()
p$x
ADDED:原型解决方案
更新:将函数名称更改为f
以与问题保持一致。
答案 1 :(得分:1)
我认为最简单的方法是只将工作副本加载到内存中,而不是加载原始(全局命名空间)和工作副本(函数命名空间)。您可以通过使用'ff'包将'x'和'y'数据集定义为'ffdf'数据帧来回避整个问题。据我了解,'ffdf'数据帧驻留在磁盘上,只在需要数据帧的一部分时加载到内存中,并在不再需要这些部分时清除。从理论上讲,这意味着数据将被加载到内存中以复制到函数名称空间中,然后在复制完成后进行清除。
我承认我很少使用'ff'包,而当我这样做时,我通常根本没有任何问题。但是,我并没有检查具体的内存使用情况,我的目标通常只是对数据进行大量计算。它有效,我不会问问题。