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

时间:2013-04-08 22:35:31

标签: r data.table

为了清除自己的一些内容,我想更好地了解复制何时以及何时不在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返回一个全新的表而不是对select元素占用的内存的引用。旧的data.table。这是正确的吗?

编辑:抱歉,我的意思是i而不是j(已在上面进行了更改)

1 个答案:

答案 0 :(得分:8)

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

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

如果我们检查data.table,那么我们可以看到truelengthtl = 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不会检查您是否只是按原始顺序返回所有行(然后仅在此情况下不复制),它只返回副本。