2014-01-17 40 views
3

我只注意到包裝中的一個小怪癖。查看下面的代碼片段以重現。鍵列更新時爲什麼鍵被丟棄?


DT = data.table(a=1:3, b=1:6); 
setkey(DT,b); 

# As expected - data is "keyed" on b 
> key(DT) 
[1] "b" 

# Now if i change content of column b, the key on the table "drops out" 
DT [,b := seq(1,6)]; 

> key(DT) 
NULL 

FYI是在R version 3.0.1 (2013-05-16)Platform (x86_64-w64-mingw32)data.table version 1.8.11

在我看來,無論何時更新密鑰列 - data.table代碼都會將密鑰完全丟棄,因爲數據內容(以及其順序)會發生變化。我希望代碼存儲密鑰,更改列b的內容,重新排列列b,並將列b恢復爲密鑰。總之,保持密鑰不變。

這與您在RDBMS databasestables中預期的行爲類似。即使數據內容發生變化,密鑰也不會丟失。

有什麼想法?

回答

4

我覺得這有點奇怪,需要改變一個關鍵值。通常希望在使用fread加載的數據旁邊添加和更新新列,或者使用RODBC從數據庫加載新列,但很少想要更改鍵列中的值,不是嗎?關鍵列通常是數據集的基礎,不會改變。

data.table對此的處理方式默認情況下是最快的。它會按照您要求的方式更改鍵列中的值,然後會丟棄鍵值,因爲它不確定鍵值是否仍然有效。如果你真的想要重建密鑰,這可能會導致整個表的重新排序,那麼只需再次明確地呼叫setkey。這樣,代碼中額外的setkey將使您的代碼的讀者清楚,對該列的更新可能會很昂貴。

data.table中的密鑰僅僅是排序順序。這更類似於SQL中的聚簇索引,其中磁盤上的行實際上是按該順序存儲的。

+0

馬特 - 感謝您的回覆。正確的是,您不會經常將數據更改爲「關鍵」列,但有少數幾個例外(我正在處理的問題涉及修改)。我不確定社區是否知道這種行爲,因此我認爲我會提出這個問題。很高興再次撥打setkey。感謝Manoj – Manoj