2014-08-28 70 views
3

我想在data.table中生成一個新的變量,我生成,保存並重新加載。加載後,我通過get()間接地處理data.table,只要我不直接爲變量創建之前的地址創建,就不會生成新變量。 可能是某種環境問題?加載data.table對象後直接生成一個新的變量(data.table)

# Generate data.table 
t<-data.table(x=c(1,2,3,4)) 
tStr<-"t" 
names(t) 

# Generate Variable a -> ok 
get(tStr)[, a:=1] 
names(t) 

# Generate Variable b -> ok 
t[, b:=1] 
names(t) 

# Save 
save(t, file="test.Robj") 
load("test.Robj", .GlobalEnv) 

# Generate Variable c -> fails 
get(tStr)[, c:=1] 
names(t) 

# Generate Variable d -> ok 
t[, d:=1] 
names(t) 

# Generate Variable e -> ok again !? 
get(tStr)[, e:=1] 
names(t) 

感謝您的幫助

+0

看起來像一個bug – eddi 2014-08-28 21:45:46

+0

[#479](https://github.com/Rdatatable/data.table/issues/479)與此類似。尚未修正。 – Arun 2014-08-28 21:56:42

+0

有關相關問題,請參閱http://stackoverflow.com/a/15208059/1385941 – mnel 2014-08-29 00:40:19

回答

4

這是因爲重要的元數據不下去的存儲動作:

> t<-data.table(x=c(1,2,3,4)) 
> attr(t, ".internal.selfref") 
<pointer: 0x0000000000100788> 
> save(t, file="test.Robj") 
> load("test.Robj", .GlobalEnv) 
> attr(t, ".internal.selfref") 
<pointer: (nil)> 
> t[, d:=1] 
> attr(t, ".internal.selfref") 
<pointer: 0x0000000000100788> 

注意如何失去記憶的指針。我不確定這是什麼data.tablesave之間的固有衝突是一個錯誤。看起來爲了這個工作正常,我們需要一個特殊的load方法,在加載data.table對象時重新分配內部指針。

在這種情況下,使用通過引用修改似乎會重置指針。

編輯:在您的使用情況下的解決方法,你可以試試:

t <- data.table(x=c(1,2,3,4)) 
save(t, file="test.Robj") 
load("test.Robj", .GlobalEnv) 
assign("t", get("t")[, c:=3]) 
t 

預期其工作原理:

x c 
1: 1 3 
2: 2 3 
3: 3 3 
4: 4 3 

還要注意的是期待:

get("t")[, c:=3] 

將工作有點像期待:

get("x") <- 5 

將工作。 data.table可能會在將來添加此功能,但它正在踩在這個暗淡的區域,其中data.table的參考性質真正開始與R語義相沖突。

+0

確實外部指針丟失。但這只是其中一部分原因。如果在加載後立即執行:'t [,c:= 1]',它就會工作,因爲它檢測到自引用無效並對其進行更正(=>淺拷貝+過度分配),添加新列然後*將新對象分配回父環境*('t'是*符號*)。但是用'get(。)[,c:= 1]',將*分配回父環境*要稍微困難。這還沒有完成(至少在這個用例中)。 – Arun 2014-08-28 22:07:49

+0

@阿倫,似乎是想要提出一些適用於任何情況的東西。我認爲在某些時候,你最終會圍繞R無引用語義(例如'colnames <-'等)開展工作,併爲這些情況提供解決方法(例如'setnames')。 – BrodieG 2014-08-29 02:10:26

+0

好吧,似乎比我教的問題更復雜,謝謝你的解決方法BrodieG,它適用於我的目的 – 2014-08-29 08:00:18