交叉比较相同data.frame的列

时间:2017-04-27 13:15:03

标签: r

我有一个看起来像这样的data.frame:

> DF1      

 A    B    C    D    E     
 a    x    c    h    p 
 c    d    q    t    w
 s    e    r    p    a
 w    l    t    s    i
 p    i    y    a    f

我想将data.frame的每一列与其余列进行比较,以计算公共元素的数量。例如,我想将列A与所有剩余列(B,C,D,E)进行比较,并以这种方式计算公共实体:

A与剩下的:

  • A vs B:0(因为它们有0个共同元素)
  • A vs C:1(c共同)
  • A vs D:2(p和s共同点)
  • A vs E:3(p,w,a,共同)

然后相同:B与C,D,E列等。

有人能帮帮我吗?我不知道如何实现这一点。

2 个答案:

答案 0 :(得分:3)

我们可以遍历列名并与其他列进行比较,方法是intersect并获取length

sapply(names(DF1), function(x) {
    x1 <- lengths(Map(intersect, DF1[setdiff(names(DF1), x)], DF1[x]))
    c(x1, setNames(0, setdiff(names(DF1), names(x1))))[names(DF1)]})
#  A B C D E
#A 0 0 1 3 3
#B 0 0 0 0 1
#C 1 0 0 1 0
#D 3 0 1 0 2 
#E 3 1 0 2 0

或者这可以通过在获得长格式化(melt)数据集的频率后获取十字产品来更紧凑地完成

library(reshape2)
tcrossprod(table(melt(as.matrix(DF1))[-1])) * !diag(5)
#    Var2
#Var2 A B C D E
#   A 0 0 1 3 3
#   B 0 0 0 0 1
#   C 1 0 0 1 0
#   D 3 0 1 0 2
#   E 3 1 0 2 0

注意:crossprod部分也通过RcppEigen here实施,这样可以加快速度

答案 1 :(得分:1)

另一种方法是使用combn两次,一次获取列组合,然后查找元素交叉点的长度。

cbind.data.frame返回data.frame,setNames用于添加列名。

setNames(cbind.data.frame(t(combn(names(df), 2)),
                 combn(names(df), 2, function(x) length(intersect(df[, x[1]], df[, x[2]])))),
         c("col1", "col2", "count"))
   col1 col2 count
1     A    B     0
2     A    C     1
3     A    D     3
4     A    E     3
5     B    C     0
6     B    D     0
7     B    E     1
8     C    D     1
9     C    E     0
10    D    E     2