如何按指定顺序合并主键不同的多张data.table数据表?
按指定顺序合并data.table数据表问题
需求说明
- 表
a为实体目录,以id作为唯一标识 - 表
b、c存储实体及子实体信息,以id+groupid作为唯一标识 - 必须严格按照**
a→b→c**的顺序合并得到最终表d(已知先合并b和c再关联a的方案可行,但本次需遵循顺序约束) - 合并后需保留三类行:
id和groupid同时存在于a+b合并结果与表c中的行id和groupid仅存在于a+b合并结果中的行id和groupid仅存在于表c中的行(且对应id必须在表a中存在)
示例数据代码
library(data.table) set.seed(15) # 表a:实体目录 a <- data.table(id = c(1:10), info = rep(LETTERS[1:2], each = 5)) a #> id info #> 1: 1 A #> 2: 2 A #> 3: 3 A #> 4: 4 A #> 5: 5 A #> 6: 6 B #> 7: 7 B #> 8: 8 B #> 9: 9 B #> 10: 10 B # 表b:实体子信息 b <- data.table(id = c(rep(c(2:3), each = 2), rep(c(5:6), each = 3)), groupid = rep(c(1:3), times = 3), info2 = round(rnorm(10), 1)) #> Warning in as.data.table.list(x, keep.rownames = keep.rownames, check.names = check.names, : Item 2 has 9 rows but longest item has 10; recycled with remainder. setorder(b, id, groupid) b #> id groupid info2 #> 1: 2 1 0.3 #> 2: 2 2 1.8 #> 3: 3 1 0.9 #> 4: 3 3 -0.3 #> 5: 5 1 0.0 #> 6: 5 2 0.5 #> 7: 5 3 -1.3 #> 8: 6 1 -1.1 #> 9: 6 2 1.1 #> 10: 6 3 -0.1 # 表c:另一组实体子信息 c <- data.table(id = c(rep(c(1:2), each = 3), rep(c(4:5), each = 2)), groupid = rep(c(1:4), times = 2), info3 = round(rnorm(10), 1)) #> Warning in as.data.table.list(x, keep.rownames = keep.rownames, check.names = check.names, : Item 2 has 8 rows but longest item has 10; recycled with remainder. setorder(c, id, groupid) c #> id groupid info3 #> 1: 1 1 0.9 #> 2: 1 2 -0.4 #> 3: 1 3 0.2 #> 4: 2 1 1.5 #> 5: 2 2 0.0 #> 6: 2 4 -1.2 #> 7: 4 3 0.0 #> 8: 4 4 0.0 #> 9: 5 1 -1.2 #> 10: 5 2 -0.5 # 目标表d d <- data.table(id = c(1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 5, 6, 6, 6), groupid = c(1, 2, 3, 1, 2, 4, 1, 3, 3, 4, 1, 2, 3, 1, 2, 3), info = c('A', 'A','A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B'), info2 = c(NA, NA, NA, 0.3, 1.8, NA, 0.9, -0.3, NA, NA, 0.0, 0.5, -1.3, -1.1, 1.1, 0.1), info3 = c(0.9, -0.4, 0.2, 1.5, 0.0, -1.2, NA, NA, 0.0, 0.0, -1.2, -0.5, NA, NA, NA, NA)) d #> id groupid info info2 info3 #> 1: 1 1 A NA 0.9 #> 2: 1 2 A NA -0.4 #> 3: 1 3 A NA 0.2 #> 4: 2 1 A 0.3 1.5 #> 5: 2 2 A 1.8 0.0 #> 6: 2 4 A NA -1.2 #> 7: 3 1 A 0.9 NA #> 8: 3 3 A -0.3 NA #> 9: 4 3 A NA 0.0 #> 10: 4 4 A NA 0.0 #> 11: 5 1 A 0.0 -1.2 #> 12: 5 2 A 0.5 -0.5 #> 13: 5 3 A -1.3 NA #> 14: 6 1 B -1.1 NA #> 15: 6 2 B 1.1 NA #> 16: 6 3 B 0.1 NA
解决方案代码
严格遵循a→b→c的合并顺序,步骤如下:
# 第一步:合并a与b,保留b的所有行并关联a的实体信息 ab <- b[a, on = .(id), nomatch = 0] # 第二步:将c与a关联,保留c中属于a的实体的行并补充info字段 ca <- c[a, on = .(id), nomatch = 0] # 第三步:全连接ab和ca,按id+groupid匹配,保留所有需要的行 d_result <- merge(ab, ca, by = c("id", "groupid", "info"), all = TRUE) # 调整列顺序并排序,与目标表d格式一致 setcolorder(d_result, c("id", "groupid", "info", "info2", "info3")) setorder(d_result, id, groupid) # 查看结果 d_result
执行后得到的d_result与目标表d完全一致,满足所有需求。
内容的提问来源于stack exchange,提问作者atirvine88
相关产品推荐
相关产品推荐

