如何计算矩阵中每个行组合的公共元素?

时间:2017-07-07 06:55:03

标签: r dataframe

我正在尝试计算数据集中每个行组合中的公共元素。我设法用一个嵌套循环来做到这一点,这个循环适用于小型数据集但是对于真实的(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))

如果进行比较,自我会更好。 非常感谢你的帮助!

2 个答案:

答案 0 :(得分:2)

使用data.table

,您可以相当快速地对所有组合(包括x a)执行此操作
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