了解 R 中 data.table 的引用属性

Posted

技术标签:

【中文标题】了解 R 中 data.table 的引用属性【英文标题】:understanding the reference properties of data.table in R 【发布时间】:2013-03-31 04:37:37 【问题描述】:

只是为了自己清理一些东西,我想更好地了解何时制作副本以及何时不在data.table 中。正如这个问题所指出的Understanding exactly when a data.table is a reference to (vs a copy of) another data.table,如果你只是简单地运行以下命令,那么你最终会修改原来的:

library(data.table)

DT <- data.table(a=c(1,2), b=c(11,12))
print(DT)
#      a  b
# [1,] 1 11
# [2,] 2 12

newDT <- DT        # reference, not copy
newDT[1, a := 100] # modify new DT

print(DT)          # DT is modified too.
#        a  b
# [1,] 100 11
# [2,]   2 12

但是,如果这样做(例如),那么您最终会修改新版本:

DT = data.table(a=1:10)
DT
     a
 1:  1
 2:  2
 3:  3
 4:  4
 5:  5
 6:  6
 7:  7
 8:  8
 9:  9
10: 10

newDT = DT[a<11]
newDT
     a
 1:  1
 2:  2
 3:  3
 4:  4
 5:  5
 6:  6
 7:  7
 8:  8
 9:  9
10: 10

newDT[1:5,a:=0L]

newDT
     a
 1:  0
 2:  0
 3:  0
 4:  0
 5:  0
 6:  6
 7:  7
 8:  8
 9:  9
10: 10

DT
     a
 1:  1
 2:  2
 3:  3
 4:  4
 5:  5
 6:  6
 7:  7
 8:  8
 9:  9
10: 10

据我了解,发生这种情况的原因是,当您执行 i 语句时,data.table 返回一个全新的表,而不是对旧 data.table 的选择元素占用的内存的引用.这是正确的和真实的吗?

编辑:对不起,我的意思是 i 不是 j(在上面进行了更改)

【问题讨论】:

即使newDT &lt;- DT[x &lt; 11] 也会创建一个副本。在通过子集创建newDT 之后执行newDT[, b := 5]。使用 tracemem.Internal(inspect(.)) 是了解这一点的信息工具。 @Arun:对不起,我不确定我是否理解你的意思..你能解释一下你指的是什么吗?你的意思是说第一个例子和第二个例子一样吗?在这种情况下是的 - 这是真的。我只是想要一个单独的例子来说明清楚。 当然,你能解释一下你在这里指的是哪个j 声明:As I understand it, the reason this happens is because when you execute a j statement,只是为了确定。我会用我当时谈到的内容写一个答案。 mnel回答的第一行基本上就是我之前的问题想搞清楚的,现在算了吧。 【参考方案1】:

当您在第二个示例中创建 newDT 时,您正在评估 i(而不是 j)。 :=j 参数中通过引用分配。 i 语句中没有等效项,因为自引用分配了列,而不是行。

data.table 是一个列表。它的长度 == 列数,但已过度分配,因此您可以添加更多列而无需复制整个表(例如,在 j 中使用 :=

如果我们检查data.table,那么我们可以看到truelength (tl = 100) -- 即列指针槽数

 .Internal(inspect(DT))
@1427d6c8 19 VECSXP g0c7 [OBJ,NAM(2),ATT] (len=1, tl=100)
  @b249a30 13 INTSXP g0c4 [NAM(2)] (len=10, tl=0) 1,2,3,4,5,...

在 data.table 中,每个元素的长度为 10tl=0。目前没有办法增加列的truelength 以允许通过引用附加额外的行。

来自?truelength

目前,它只是列指针的列表向量 过度分配(即真长度(DT)),而不是列向量 他们自己,这将在未来允许快速行插入()

当您评估 i 时,data.table 不会检查您是否简单地以与原始相同的顺序返回所有行(然后在这种情况下不复制),它只是返回副本。

【讨论】:

优秀的答案,像往常一样!我会避免尴尬并放弃我的答案:)。 @mnel:我想我的问题并不完全清楚,或者我不完全理解你的答案。我的意思是了解,当您评估 i 时,是否返回副本而不是参考。这是真的吗? @Alex 正是——我已经改写了我的最后陈述(在二读时不是特别清楚)

以上是关于了解 R 中 data.table 的引用属性的主要内容,如果未能解决你的问题,请参考以下文章

使用带有R内核的jupyter笔记本,如何通过引用来抑制打印结果更新data.table?

R之data.table 介绍

R 中 data.table 的 colnames() 行为

如何在sum()语句中通过其位置引用data.table的列

在 R 的 data.table 中获取随机的内部 selfref 错误

R:尝试转换 data.table 时出错