根据另一个 data.table 中的值更新 data.table

Posted

技术标签:

【中文标题】根据另一个 data.table 中的值更新 data.table【英文标题】:update data.table based on values in another data.table 【发布时间】:2014-09-29 10:24:48 【问题描述】:

我正在尝试根据另一个表中的值更新 data.table。我以为我有一种方法(虽然考虑到我的实际 dt2 有 350 万条记录,但效率不是特别高),但事实证明我的代码出了点问题

在 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;其中瓮的分类为 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 个数据连接。正如我所说,350 万条记录会增加一些开销(尤其是当我实际上要为大约 10 列设置标志时)。

提前致谢。

【问题讨论】:

dcast(dt1[dt2,], urn~classification) 之类的东西可能会起作用 【参考方案1】:

您可以为此使用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

【讨论】:

这看起来非常有希望,但我似乎无法让它与我的真实数据一起工作。在我的真实世界数据中,我确实在 dt1 和 dt2 中有许多其他列。这是否可能对上述工作方式产生负面影响,鉴于上述所有内容似乎都已命名,我不会怀疑......到目前为止,我真的很感谢您的帮助。 [我将在接下来的几个小时内参加会议,因此可能需要一段时间才能回复] 你能做一个可重复的例子吗,这不起作用?或者至少打印您收到的错误消息?否则很难诊断问题。 感谢@shadow,我意识到我的方式错误。在没有更新 dt1 的情况下运行代码后,我再次检查了 dt1 的内容。我想了一个办法。谢谢我确实有我的问题的另一个扩展,如果我想使用 V3 的 8 而不是 V3 的值 6,我会收到一个错误,因为 dt2 没有任何分类 = 8 的记录。我希望能够使它成为一段相当通用的代码,这将能够解释一系列分类的存在,但如果这些分类不存在,也不会失败。有什么建议吗?

以上是关于根据另一个 data.table 中的值更新 data.table的主要内容,如果未能解决你的问题,请参考以下文章

涉及因素的数据表分配

根据另一个表中的值更新表中的值[重复]

根据以前的值更新列值(一次处理总是处理)

根据另一个表中的值更新视图

根据另一个表中的值插入和/或更新记录

根据另一行中的值更新一行