R:通过引用传递数据帧

时间:2012-06-26 12:37:34

标签: performance r dataframe data.table proto

R具有按值传递的语义,可以最大限度地减少意外的副作用(这是一件好事)。然而,当代码被组织成许多用于可重用性/可读性/可维护性的函数/方法时,并且当代码需要通过例如大数据帧来操纵大数据结构时,通过一系列转换/操作,传递值语义引导大量复制数据和堆积颠簸(一件坏事)。例如,在作为函数参数传递的堆上占用50Mb的数据帧将至少复制与函数调用深度相同的次数,并且调用堆栈底部的堆大小将为N * 50MB。如果函数从调用链的深处返回转换/修改的数据帧,则复制将由另一个N上升。

SO问题What is the best way to avoid passing a data frame around?触及了这个主题,但是以避免直接询问传递参考问题的方式表达,而获胜的答案基本上说,“是的,值传递是R的工作原理”。这实际上不是100%准确。 R环境支持传递引用语义,而proto等OO框架广泛使用此功能。例如,当一个proto对象作为函数参数传递时,当它的“魔术包装器”通过值传递给R开发人员时,语义就是传递引用。

似乎通过引用传递大数据框架将是一个常见问题,我想知道其他人是如何接近它的,以及是否有任何库可以实现这一点。在我的搜索中,我没有发现一个。

如果没有可用的东西,我的方法是创建一个包装数据框的proto对象。我希望有关应该添加到此对象的语法糖的指针,以使其有用,例如,重载$和[[运算符,以及我应该注意的任何陷阱。我不是R专家。

与类型无关的传递参考解决方案的奖励积分与R很好地集成,尽管我的需求仅限于数据框。

1 个答案:

答案 0 :(得分:28)

问题的前提是(部分)不正确。 R作为pass-by-promise工作,并且只有在传递承诺时进行数据帧的进一步分配和更改时,才会以您概述的方式重复复制。因此,副本的数量将不是N *大小,其中N是堆栈深度,而是其中N是进行分配的级别数。但是,您是正确的,环境可能很有用。我看到你已经找到'proto'包的链接。还有一个相对较新的“引用类”的引入,有时被称为“R5”,其中R / S3是在R中复制的S3的原始类系统,R4将是最近似乎主要支持的类系统BioConductor包开发。

这是一个链接到Steve Lianoglou(在一个讨论引用类的优点的线程中)在S4对象中嵌入环境以避免复制成本的示例的链接:

https://stat.ethz.ch/pipermail/r-help/2011-September/289987.html

Matthew Dowle的'data.table'包创建了一个新类的数据对象,其使用“[”的访问语义与常规R data.frames的访问语义不同,并且它实际上是作为pass-by-reference工作的。它具有出色的访问和处理速度。它也可以依赖于数据框语义,因为在以后的几年里,这些对象现在继承了'data.frame'类。

您可能还想调查Hesterberg's dataframe package