【发布时间】:2023-04-03 05:57:01
【问题描述】:
问题
我想写一个函数,修改一个大矩阵的每一列,x:
f = function(x){
# do something to x
# return x
}
因为 x 非常大,我想“就地”修改它,即不创建副本。但是,我的理解是,在 R 中,函数是“修改时复制”。换句话说,如果我在函数 f 中修改 x,R 将复制 x。
建议的解决方案(更新:不起作用!有关详细信息,请参阅下面的答案。)
因此,看来最好的解决办法是修改全局变量,即
f = function(x){
x = deparse(substitute(x))
x = get(x, envir = globalenv())
# do something to x
}
问题
但是,SO 上的人们对于将全局变量传递给 R 中的函数非常消极。有些人甚至仅仅因为询问它而被否决。
我的问题是:在 R 中执行此类操作的最佳方法是什么?
【问题讨论】:
-
我很确定您提出的解决方案仍会在 f 中创建一个副本,但我很想对其进行测试。
-
data.table包。常规 R 函数中的赋值仍然会生成中间 temp 副本。避免这种情况的唯一方法是重新定义 [ -
我很好奇哪些问题被否决了“将全局变量传递给函数” ...除了最严格的环境之外,这在所有环境中都是不可避免的。相反,我可以相信:通过违反词法范围从函数内部访问(甚至修改)全局变量,而不被传递。有时,纯函数式方法可能效率低下,但不受控制的副作用使调试和代码维护极其困难。不幸的是,正如@42- 所建议的那样,R 几乎完全是关于 ref-by-copy 和 copy-on-write,
data.table是一个值得注意的例外。 -
data.table在这种情况下会有所帮助。例如:修改选择的列cols <- names(dt)[c(1, 5, 10)]; dt[, (cols) := lapply(.SD, function(x) x/mean(x)), .SDcols = cols] -
@Tung,在您的解决方案中,我很好奇使用了多少内存?我的理解是 data.table 在内存中创建两个对象(原始数据表和均值表),然后用另一个替换一个?还是原始表中的每一列在计算出新的中心值后立即被替换?
标签: r memory memory-management global