当表被"复制时,data.table中的二级密钥("索引"属性)将丢失。通过选择列

时间:2016-01-24 15:13:23

标签: r data.table

我有一个data.table myDT,我正在制作"副本"这个表有三种不同的方式:

myDT <- data.table(colA = 1:3)
myDT[colA == 3]

copy1 <- copy(myDT)
copy2 <- myDT # yes I know that it's a reference, not real copy
copy3 <- myDT[,.(colA)] # I list all columns from the original table

然后我将这些副本与原始表格进行比较:

identical(myDT, copy1) 
# TRUE
identical(myDT, copy2)
# TRUE
identical(myDT, copy3)
# FALSE

我试图找出myDTcopy3

之间的区别
identical(names(myDT), names(copy3))
# TRUE
all.equal(myDT, copy3, check.attributes=FALSE)
# TRUE
all.equal(myDT, copy3, check.attributes=FALSE, trim.levels=FALSE, check.names=TRUE)
# TRUE
attr.all.equal(myDT, copy3, check.attributes=FALSE, trim.levels=FALSE, check.names=TRUE)
# NULL
all.equal(myDT, copy3)
# [1] "Attributes: < Length mismatch: comparison on first 1 components >"
attr.all.equal(myDT, copy3)
# [1] "Attributes: < Names: 1 string mismatch >"                                         
# [2] "Attributes: < Length mismatch: comparison on first 3 components >"                
# [3] "Attributes: < Component 3: Attributes: < Modes: list, NULL > >"                   
# [4] "Attributes: < Component 3: Attributes: < names for target but not for current > >"
# [5] "Attributes: < Component 3: Attributes: < current is not list-like > >"            
# [6] "Attributes: < Component 3: Numeric: lengths (0, 3) differ >"

我最初的问题是如何理解最后的输出。最后我开始使用attributes()函数:

attr0 <- attributes(myDT)
attr3 <- attributes(copy3)
str(attr0)
str(attr3)

它显示原始data.table具有index属性,在创建copy3时未复制该属性。

1 个答案:

答案 0 :(得分:4)

为了使这个问题更清晰一点(也许对未来的读者有用),这里真正发生的是你(可能不是)在显式调用{{1}时设置二级密钥 },OR,set2key在进行一些普通操作(如过滤)时,似乎设置了辅助密钥。这是V 1.9.4中添加的(不是那样的)新功能

  

DT [column == value]和DT [%%in%values]现在已经过优化使用   密钥(DT)[1] ==&#34;列&#34;时的DT键,否则为辅助密钥(a.k.a.   index)会自动添加,因此下一个DT [column == value]就是多了   快点。无需更改代码;现有代码应该自动进行   效益。可以使用set2key()和手动添加辅助键   使用key2()检查存在。这些优化和功能   名称/参数是实验性的,可以关闭   选项(datatable.auto.index = FALSE)。

让我们重现这个

data.table

因此,与您假设的不同,您实际上 创建了一个副本,因此辅助密钥并未随之传输。比较

myDT <- data.table(A = 1:3)
options(datatable.verbose = TRUE)
myDT[A == 3]    
# Creating new index 'A' <~~~~ Here it is
# forder took 0 sec
# Coercing double column i.'V1' to integer to match type of x.'A'. Please avoid coercion for efficiency.
# Starting bmerge ...done in 0 secs
# A
# 1: 3

attr(myDT, "index") # or using `key2(myDT)`
# integer(0)
# attr(,"__A")
# integer(0)

进行进一步验证

copy1 <- myDT
attr(copy1, "index")
# integer(0)
# attr(,"__A")
# integer(0)
copy2 <- myDT[,.(A)]
# Detected that j uses these columns: A <~~~ This is where the copy occures
attr(copy2, "index")
# NULL

identical(myDT, copy1)
# [1] TRUE
identical(myDT, copy2)
# [1] FALSE

这里最有趣的结论是,tracemem(myDT) # [1] "<00000000159CBBB0>" tracemem(copy1) # [1] "<00000000159CBBB0>" tracemem(copy2) # [1] "<000000001A5A46D8>" 创建副本,即使对象保持不变。