2012-06-25 71 views
6

我注意到在使用不同賦值運算符時data.table中存在一些不一致(與我不一致)的行爲。我不得不承認,我從來沒有弄清楚「=」和copy()之間的區別,所以我們可以在這裏說明一些情況。如果在更改複製的data.table時使用「=」或「< - 」而不是以下的copy(),則原始data.table也會發生變化。data.table 1.8.1 .:「DT1 = DT2」與DT1 = copy(DT2)不同?

請執行以下命令,你會明白我的意思

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。不是如果我使用副本():

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 

是這種行爲的預期?

回答

10

是的。這是預期的行爲,並有據可查。

由於data.table使用對原始對象的引用來實現就地修改,因此它非常快速。

出於這個原因,如果你真的複製數據,您需要使用copy(DT)


從文檔?copy

的data.table被修改參考,並返回(無形)所以 它可以在複合語句中使用;例如,setkey(DT,a)[J("foo")]。 如果您需要複印件,請先複印一份(使用DT2=copy(DT))。 copy() 在使用:=作爲引用的副列分配給 之前有時也會有用。見?copy

也看到這個問題: Understanding exactly when a data.table is a reference to vs a copy of another

+0

感謝@Andrie。我明白通過引用來賦值,以及爲什麼要避免首先複製。對我來說,似乎奇怪的是,'='在副本和原始文件之間創建了一個鏈接,就好像它們是同一個對象(否則在R中不是這種情況)。 –

+0

@FlorianOswald我同意 - 如果一個人不小心,這可能是一個陷阱。 – Andrie

+1

+10如果我可以安德烈。 @Florian想象一下內存中的20GB +表。我們絕對不想複製它,甚至一次。但如果你真的想,你可以。它不會破壞與其他軟件包的兼容性,因爲它只是通過引用分配的':='和'set *'函數。這是我們引入新運算符(':=')的原因之一,而不是使'<-'以不同的方式工作。 –

相關問題