6

在使用不同的赋值运算符时,我注意到 data.table 中存在一些不一致(对我来说不一致)的行为。我不得不承认我从来没有完全理解“=”和 copy() 之间的区别,所以也许我们可以在这里阐明一下。如果您在下面使用“=”或“<-”而不是 copy(),则在更改复制的 data.table 时,原始 data.table 也会更改。

请执行以下命令,你会明白我的意思

library(data.table)
example(data.table)

DT
   x y  v
1: a 1 42
2: a 3 42
3: a 6 42
4: b 1  4
5: b 3  5
6: b 6  6
7: c 1  7
8: c 3  8
9: c 6  9

DT2 = DT

现在我将更改 DT2 的 v 列:

DT2[ ,v:=3L]
   x y  v
1: a 1  3
2: a 3  3
3: a 6  3
4: b 1  3
5: b 3  3
6: b 6  3
7: c 1  3
8: c 3  3
9: c 6  3

但看看 DT 发生了什么:

DT
   x y  v
1: a 1  3
2: a 3  3
3: a 6  3
4: b 1  3
5: b 3  3
6: b 6  3
7: c 1  3
8: c 3  3
9: c 6  3

它也改变了。所以:改变DT2改变了原来的DT。如果我使用 copy() 则不是这样:

example(data.table)  # reset DT
DT3 <- copy(DT)
DT3[, v:= 3L]
   x y  v
1: a 1  3
2: a 3  3
3: a 6  3
4: b 1  3
5: b 3  3
6: b 6  3
7: c 1  3
8: c 3  3
9: c 6  3

DT
   x y  v
1: a 1 42
2: a 3 42
3: a 6 42
4: b 1  4
5: b 3  5
6: b 6  6
7: c 1  7
8: c 3  8
9: c 6  9

这种行为是预期的吗?

4

1 回答 1

11

是的。这是预期的行为,并且有据可查。

由于data.table使用对原始对象的引用来实现就地修改,因此速度非常快。

出于这个原因,如果你真的想复制数据,你需要使用copy(DT)


从文档中?copy

data.table 通过引用修改,并返回(不可见),因此可以在复合语句中使用;例如,setkey(DT,a)[J("foo")]。如果您需要一份副本,请先复制一份(使用DT2=copy(DT))。在用于通过引用对列进行子分配copy() 之前有时也可能很有用。:=?copy

另请参阅此问题: 准确了解 data.table 何时是对另一个副本的引用

于 2012-06-25T15:35:32.230 回答