2014-09-29 68 views
1

我試圖根據另一個表中的值更新data.table。我認爲我有一個辦法(雖然不是特別有效,因爲我的實際dt2有3.5M記錄),但事實證明我的代碼有問題根據另一個data.table中的值更新data.table

在DT1我有一些我想要的變量(數字)取決於它們的分類值是什麼來設置爲1或0。數據

例子:

dt1 <- data.table(urn = 1:10, V1=0,V2=0,V3=0) 
## urn V1 V2 V3 
## 1: 1 0 0 0 
## 2: 2 0 0 0 
## 3: 3 0 0 0 
## 4: 4 0 0 0 
## 5: 5 0 0 0 
## 6: 6 0 0 0 
## 7: 7 0 0 0 
## 8: 8 0 0 0 
## 9: 9 0 0 0 
##10: 10 0 0 0 

dt2 <- data.table(urn=rep(1:10,2),classification=0) 
dt2$classification <- 1:7 #does give a warning message 
## urn classification 
## 1: 1    1 
## 2: 2    2 
## 3: 3    3 
## 4: 4    4 
## 5: 5    5 
## 6: 6    6 
## 7: 7    7 
## 8: 8    1 
## 9: 9    2 
##10: 10    3 
##11: 1    4 
##12: 2    5 
##13: 3    6 
##14: 4    7 
##15: 5    1 
##16: 6    2 
##17: 7    3 
##18: 8    4 
##19: 9    5 
##20: 10    6 

我希望發生的就是骨灰盒相匹配,和甕有1分的紀錄,然後設置V1標誌爲1;其中urn分類爲2,設置V2 = 1;你明白了。

我目前的做法是:

setkey(dt1, urn) 
setkey(dt2, urn) 
dt1[dt2, V1:= ifelse(i.classification == 1 , 1, dt1$V1)] 
dt1[dt2, V2:= ifelse(i.classification == 2, 1, dt1$V2)] 
dt1[dt2, V3:= ifelse(i.classification == 6, 1, dt1$V3)] 
dt1 
## urn V1 V2 V3 
## 1: 1 1 0 0 
## 2: 2 1 0 0 
## 3: 3 1 0 1 
## 4: 4 1 0 0 
## 5: 5 1 0 0 
## 6: 6 1 1 0 
## 7: 7 1 0 0 
## 8: 8 1 0 0 
## 9: 9 1 0 0 
##10: 10 1 0 1 

我其實希望輸出的樣子是:

## urn V1 V2 V3 
## 1: 1 1 0 0 
## 2: 2 0 1 0 
## 3: 3 0 0 1 
## 4: 4 0 0 0 
## 5: 5 1 0 0 
## 6: 6 0 1 1 
## 7: 7 0 0 0 
## 8: 8 1 0 0 
## 9: 9 0 1 0 
##10: 10 0 0 1 

任何幫助將不勝感激。特別是如果我能夠簡化命令以在一次掃描中管理所有這些命令而不是3次連接的數據。正如我所說的3.5M記錄增加了一些開銷(特別是當我實際上將設置約10列的標誌)。

在此先感謝。

+0

像'dcast(DT1 [DT2],甕〜分類)'可能工作 – shadow 2014-09-29 10:35:29

回答

2

您可以使用dcast.data.table

dcast.data.table(data = dt1[dt2,], 
     formula = urn ~ classification, 
     fun.aggregate = function(x) as.numeric(any(!is.na(x))), 
     value.var = 'classification')[, list(urn, V1=`1`, V2=`2`, V3=`6`)] 
##  urn V1 V2 V3 
## 1: 1 1 0 0 
## 2: 2 0 1 0 
## 3: 3 0 0 1 
## 4: 4 0 0 0 
## 5: 5 1 0 0 
## 6: 6 0 1 1 
## 7: 7 0 0 0 
## 8: 8 1 0 0 
## 9: 9 0 1 0 
## 10: 10 0 0 1 

編輯:必要時,可以包裹的最後一條語句中tryCatch功能:

dcast.data.table(data = dt1[dt2,], 
       formula = urn ~ classification, 
       fun.aggregate = function(x) as.numeric(any(!is.na(x))), 
       value.var = 'classification')[, list(urn, 
                 V1=tryCatch(`1`, error =  ## function(e) NA), 
                 V2=tryCatch(`2`, error = function(e) NA), 
                 V3=tryCatch(`8`, error = function(e) NA))] 
##  urn V1 V2 V3 
## 1: 1 1 0 NA 
## 2: 2 0 1 NA 
## 3: 3 0 0 NA 
## 4: 4 0 0 NA 
## 5: 5 1 0 NA 
## 6: 6 0 1 NA 
## 7: 7 0 0 NA 
## 8: 8 1 0 NA 
## 9: 9 0 1 NA 
## 10: 10 0 0 NA 
+0

這看起來非常有前途,但我似乎無法讓它與我的真實數據一起工作。在我的真實世界數據中,我在dt1&dt2中有許多其他列。這可能會對上述工作產生負面影響,我不會懷疑這樣做,因爲所有內容似乎都在上面提及......真的非常感謝迄今的幫助。 [我將在接下來的幾個小時參加會議,因此可能需要一段時間才能回覆] – Dan 2014-09-29 18:08:08

+0

您可以製作一個可重複的示例嗎?或者至少打印你得到的錯誤信息?否則,診斷問題非常困難。 – shadow 2014-09-30 06:52:31

+0

謝謝@shadow,我意識到我的方式錯誤。我在沒有更新dt1的情況下運行代碼後再次檢查dt1的內容。我已經想通了。謝謝 雖然我的問題還有另外一個擴展,但如果不是V3的值爲6,我想爲V3使用8,我得到一個錯誤,因爲dt2沒有任何分類= 8的記錄。我希望能夠使這是一個相當通用的代碼片段,這將能夠說明存在一系列的分類,但如果這些分類不存在,則不會落空。有小費嗎? – Dan 2014-09-30 19:42:31

相關問題