大家好,我正在寻找一种在每个单元格中存储向量的方法,这是示例数据集。
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
变量来指示 set.a
和 的交集>set.b
按每个 id 看起来像
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
最佳答案
我们可以使用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
的“set.a” ,按“id”列和 paste
分组使用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
的元素在我们 rbind
之后的 'id' 列的 'set.a' 中两个数据集。
rbindlist(list(dt1, dt2))[,
.(set.a = toString(set.a[duplicated(set.a)])), by = id]
关于r - 按组在每个单元格中存储一个向量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32793422/