大家好,我正在寻找一种在每个单元格中存储矢量的方法,这里是样本数据集。
dt1 <- data.table(id = rep(1:2, each = 3), set.a = c(5,1,3,10,4,7))
dt1
id set.a
1: 1 5
2: 1 1
3: 1 3
4: 2 10
5: 2 4
6: 2 7
现在我想要的是一种将dt1
转换为这样的方法:
id set.a
1: 1 5,1,3
2: 2 10, 4, 7
这个问题可能非常基本,但确实耗费了我近一个小时。事实上,它是另一份工作的一部分。假设我有另一个数据集:
dt2 <- data.table(id = rep(1:2, each = 3), set.b = c(3,5,9,8,10,4))
dt
id set.b
1: 1 3
2: 1 5
3: 1 9
4: 2 8
5: 2 10
6: 2 4
我真正想要的是如何计算每个id的重叠,即overlap
变量,以指示每个id的set.a
和set.b
的交叉点看起来像
id overlap
1: 1 5,3
2: 2 10, 4
为了实现这一点,我计划首先将每个id的set
变量聚合到一个向量中,然后计算它们的交集,但是我没有在每个单元格中存储一个向量,就像我在开头提到的那样。有人可以帮帮我吗?提前谢谢。
我尝试了akrun和Frank的方式,发现data.table合并方式更有效率。这是一个小基准,谢谢你们两个:)
dt1 <- data.table(id = rep(1:10000, each = 10), set1 = sample(letters[1:24], 100000, replace = T))
dt2 <- data.table(id = rep(1:10000, each = 10), set2 = sample(letters[1:24], 100000, replace = T))
system.time({
re1 <- rbindlist(list(dt1, dt2), idcol=TRUE)[,
.(overlap=toString(intersect(set1[.id==1], set1[.id==2]))) , by =id]
})
# 0.25s
system.time({
re2 <- dt1[dt2, on = c(id = "id", set1 = "set2"), nomatch = 0][, .(ovlp = list(unique(set1))), by = "id"]
})
# 0.07s
system.time({
dt3 <- dt1[, .(set1 = list(set1)), by = id]
dt4 <- dt2[, .(set2 = list(set2)), by = id]
re3 <- dt3[dt4, nomatch = 0, on = "id"][, .(ov = list(intersect(unlist(set1), unlist(set2)))), by = id]
})
# 0.21s
答案 0 :(得分:3)
我们可以使用toString
到paste
'set.a'中的元素,按'id'变量分组。
dt1[, .(set.a=toString(set.a)), by = id]
# id set.a
#1: 1 5, 1, 3
#2: 2 10, 4, 7
对于第二种情况,我们rbind
将rbindlist(list(...)
数据集添加到单个数据集(idcol=TRUE
)和intersect
。获取.id
的'{1}}的'{1}},使用paste
将“id”列和toString
元素分组在一起。
rbindlist(list(dt1, dt2), idcol=TRUE)[,
.(overlap=toString(intersect(set.a[.id==1], set.a[.id==2]))) , by =id]
# id overlap
#1: 1 5, 3
#2: 2 10, 4
或者@Richard Scriven在评论中提到,paste
我们duplicated
后{id}列中'{1}}中rbind
的元素。数据集。
rbindlist(list(dt1, dt2))[,
.(set.a = toString(set.a[duplicated(set.a)])), by = id]
答案 1 :(得分:1)
我会使用合并:
res <- merge(
dt1[, .(a = list(set.a)), by=id], # <- answer to the first question
dt2[, .(b = list(set.b)), by=id],
by="id"
)[,
overlap := .(Map(intersect, a, b))
]
# id a b overlap
# 1: 1 5,1,3 3,5,9 5,3
# 2: 2 10, 4, 7 8,10, 4 10, 4
如果速度是一个问题,我怀疑这更快:
dt1[dt2, on = c(id = "id", set.a = "set.b"), nomatch=0][,
.(overlap = list(set.a))
, by=id]
# id overlap
# 1: 1 3,5
# 2: 2 10, 4
dt1[dt2,...]
只是另一种合并/加入。