在data.table中进行浅复制

5
我在一个SO主题中读到了Matt Dowle的回答,他提到了一个用于在data.table中创建浅拷贝的shallow函数。然而,我无法再次找到这个主题。 data.table没有任何导出名为shallow的函数。虽然有一个内部函数,但没有文档记录。我能安全地使用它吗?它的行为是什么?
我想做的是对一个大表进行内存高效的复制。假设DT是一个具有n列的大表,f是一种内存高效添加列的函数。这种操作是否可行?
DT2 = f(DT)

如果DT2是一个指向原始地址的具有n列的data.table(没有深度复制),并且仅存在于DT2中,则会发生什么? 如果我执行DT2 [,col3:= NULL],则DT1会发生什么变化?

1个回答

4
您不能安全地使用data.table:::shallow,这是故意不导出的并且不适合用户使用。无论从它本身工作的角度,还是从它的名称或参数在将来发生更改的角度来看,都是如此。
话虽如此,只要您确保 := set *不会被您或您的用户(如果您正在创建一个软件包)调用结果,或者如果调用:= set *在结果上,则您可以决定使用它,然后您可以接受通过引用同时更改两个对象。当数据表内部使用shallow时,我们承诺这一点。
更多背景信息请参见此处几天前的答案: https://dev59.com/M1cO5IYBdhLWcg3wZQzX#45891502 在那个问题中,我询问了更大的情况:为什么需要这样做?清楚这一点将有助于提高调查ALTREP或可能进行自己的引用计数的优先级。
在您的问题中,您暗示您的更大情况非常有用。因此,您想创建一个函数,在函数内将工作列添加到大型数据表中,但不更改大型数据表。您能否解释一下为什么要创建这样的函数?为什么不加载大型数据表,直接将临时工作列添加到其中,然后继续进行。您的R会话已经是内存中数据的工作副本,而这些数据是存储在其他地方的。
请注意,我并没有说不行。我并不是说您没有有效的理由。我正在寻找更多有关有效原因的信息,以提高优先级。
如果那不是您所看到的答案,则搜索字符串“ [data.table] shallow”当前返回39个问题或答案。最坏的情况下,您可以查找其中的答案。

谢谢。其实这更多或少是一个问题,为了更好地理解 data.table 中的浅层复制而问自己的。但也为我的用户考虑。实际上,用户不熟悉引用更新。我的一些函数都像 set* 函数一样设计,并通过引用添加列。但我经常收到电子邮件询问为什么函数返回 NULL(invisible()),即使文档清楚地说明了内部行为。我想知道是否浅拷贝可以使工作流程更简单,同时也具有相同的内存效率。 - JRR
要明确一点:我从来没有认为我的想法是一个好主意。我也没有计划编写这样的功能。实际上,我喜欢 set* 语义,它是最好的方式,也是最安全的方式。我只是在质疑技术可能性,因为我喜欢技术问题。 - JRR
关于为什么,我有一个函数被optim多次调用,它会创建动态确定数量的列,而这些列在函数外部是不需要的。使用shallow代替原始输入,我可以避免清除这些列时的麻烦。我还将其与一次性函数一起使用,只是为了避免担心我的输入数据被搞乱;我想我可以为这些函数切换到使用copy - Frank
1
谢谢大家。 我同意这是必要的。 所以我在问什么呢? 我想提供一个可运行的示例,展示一些非平凡的东西,表明需要和我可以进行测试。 我认为copy()DT[,..someCols]都可以更改为返回浅复制,然后可以删除内部的“shallow”。 只要:=能够可靠地读取列的引用计数(这之前是问题)。 - Matt Dowle
1
提供一个可运行的公共数据示例作为文章基础,肯定有助于提高优先级。特别是如果有其他人撰写它的话。 - Matt Dowle
我完全同意。非常赞同! DT[,..someCols] 可以更改为返回浅层。 - JRR

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接