2014-09-29 74 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

相关问题