【发布时间】:2012-06-27 18:44:03
【问题描述】:
R 具有按值传递的语义,可以最大限度地减少意外副作用(一件好事)。但是,当代码被组织成许多函数/方法以实现可重用性/可读性/可维护性时,以及当代码需要通过例如大数据帧、通过一系列转换/操作来操作大型数据结构时,传递值语义会导致大量的数据复制和大量的堆颠簸(一件坏事)。例如,在作为函数参数传递的堆上占用 50Mb 的数据帧将至少复制与函数调用深度相同的次数,并且调用堆栈底部的堆大小将为 N* 50MB。如果函数从调用链的深处返回一个转换/修改的数据帧,那么复制会增加另一个 N。
SO 问题What is the best way to avoid passing a data frame around? 涉及该主题,但措辞方式避免直接询问传递引用问题,而获胜的答案基本上是说:“是的,传递值是 R 的工作方式”。这实际上并不是 100% 准确的。 R 环境支持按引用传递语义,而 OO 框架(例如 proto)广泛使用此功能。例如,当一个 proto 对象作为函数参数传递时,它的“魔术包装器”是按值传递的,对于 R 开发人员来说,语义是按引用传递的。
似乎通过引用传递大数据框将是一个常见问题,我想知道其他人如何处理它以及是否有任何库可以实现这一点。在我的搜索中,我没有发现一个。
如果没有可用的东西,我的方法是创建一个包装数据框的原型对象。我会很感激有关应该添加到该对象以使其有用的语法糖的指针,例如,重载 $ 和 [[ 运算符,以及我应该注意的任何陷阱。我不是 R 专家。
与 R 完美集成的与类型无关的按引用传递解决方案的奖励积分,尽管我的需求完全是数据帧。
【问题讨论】:
-
我认为您问题中的前提不正确。 R 仅在更改时复制,因此只要不更改对象,您就可以愉快地将参数传递到调用堆栈而无需创建新副本。我会在一分钟内尝试为您找到一些关于此的参考资料。
-
查看例如这个问题及其@matthewdowle 的回答:stackoverflow.com/q/10225098/602276
-
安德烈是对的。很惊讶您在搜索大型
data.frame时没有找到data.table。你搜索了什么? -
@Andrie,感谢您指出这一点。我很惊讶它没有在R 编程的艺术 等书籍中提及。它似乎是一个基本的语言特征。您推荐的关于 R 内部的最佳读物是什么?
标签: performance r dataframe data.table proto