根据另一个 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的主要内容,如果未能解决你的问题,请参考以下文章