我正在尝试计算数据集中每个行组合中的公共元素。我设法用一个嵌套循环来做到这一点,这个循环适用于小型数据集但是对于真实的(1380 * 1380组合)需要太长时间。我想知道是否有一种简单且计算量较小的方法来实现它。
a <- c(1,5,6,8,9)
b <- c(4,3,6,8,2)
c <- c(4,3,6,1,9)
df <- rbind(a,b,c)
结果应如下所示
data.frame(p1= c('a','a','a','b','b','b','c','c','c'),
p2= c('a','b','c','a','b','c','a','b','c'),
res= c(5,2,2,2,5,3,2,3,5))
如果进行比较,自我会更好。 非常感谢你的帮助!
答案 0 :(得分:2)
使用data.table
:
library(data.table)
# Set up data.table
DT <- data.table(p = c("a","b","c"), vec = c(list(a), list(b), list(c)))
DT[, JA := 1]
DT <- merge(DT, DT, by = "JA", allow.cartesian = TRUE)
# calculate intersection
DT[, length(intersect(unlist(vec.x),unlist(vec.y))), by = .(p.x, p.y)]
p.x p.y V1
1: a a 5
2: a b 2
3: a c 3
4: b a 2
5: b b 5
6: b c 3
7: c a 3
8: c b 3
9: c c 5
您的数据可能有些棘手的问题是使用列表列初始化您的data.table,但这取决于您当前存储的1380个向量的方式。
要过滤掉x a,只需使用:
DT[p.x != p.y]
此解决方案非常快,在~12秒内处理100万行
DT2 <- data.table(p.x = 1:1000000, p.y = 1:1000000)
DT2[, vec.x := rep(list(a), 1e6)]
DT2[, vec.y := rep(list(b), 1e6)]
system.time(DT2[, length(intersect(unlist(vec.x),unlist(vec.y))), by = .(p.x, p.y)])
user system elapsed
11.80 0.03 12.00
编辑:在重新阅读你的例子之后,可能不是你所需要的。如果元素的顺序很重要,请改用以下内容:
DT[, length(which(unlist(vec.x) == unlist(vec.y))), by = .(p.x, p.y)]
p.x p.y V1
1: a a 5
2: a b 2
3: a c 2
4: b a 2
5: b b 5
6: b c 3
7: c a 2
8: c b 3
9: c c 5
答案 1 :(得分:1)
如果您不需要比较相同的行(即a与a),那么combn
可以如下工作,
combn(1:nrow(df), 2, FUN = function(i) sum(df[i[1],] - df[i[2],]==0))
#[1] 2 2 3
# or add the names of combinations as well,
setNames(combn(1:3, 2, FUN = function(i) sum(df[i[1],] - df[i[2],]==0)),
combn(rownames(df), 2, toString))
#a, b a, c b, c
# 2 2 3