计算 R 列表中元素对的数量?

Ele*_*ino 11 r

关于计数对也提出了类似的问题,但是似乎没有一个对于我想做的事情特别有用。

我想要的是计算多个列表元素之间的对数并将其转换为矩阵。例如,如果我有一个像这样的列表:

myList <- list(
  a = c(2,4,6),
  b = c(1,2,3,4),
  c = c(1,2,5,7),
  d = c(1,2,4,5,8)
)
Run Code Online (Sandbox Code Playgroud)

我们可以看到该对出现了 3 次( 、 、和1:2中各出现一次)。该对仅在 中出现一次。该对出现 2 次(在和中各出现一次)...等等。abc1:3b1:4bd

我想计算一对出现的次数,然后将其转换为对称矩阵。例如,我想要的输出看起来像我手动创建的矩阵(其中矩阵的每个元素都是该对值的总计数):

> myMatrix
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,]    0    3    1    2    2    0    1    1
[2,]    3    0    1    3    2    1    1    1
[3,]    1    1    0    1    0    0    0    0
[4,]    2    3    1    0    0    0    0    1
[5,]    2    2    0    0    0    0    1    1
[6,]    0    1    0    0    0    0    0    0
[7,]    1    1    0    0    1    0    0    0
[8,]    1    1    0    1    1    0    0    0
Run Code Online (Sandbox Code Playgroud)

任何建议都非常感激

the*_*ail 9

受@akrun的回答的启发,我认为你可以使用叉积来非常快速、简单地得到这个:

out <- tcrossprod(table(stack(myList)))
diag(out) <- 0

#      values
#values 1 2 3 4 5 6 7 8
#     1 0 3 1 2 2 0 1 1
#     2 3 0 1 3 2 1 1 1
#     3 1 1 0 1 0 0 0 0
#     4 2 3 1 0 1 1 0 1
#     5 2 2 0 1 0 0 1 1
#     6 0 1 0 1 0 0 0 0
#     7 1 1 0 0 1 0 0 0
#     8 1 1 0 1 1 0 0 0
Run Code Online (Sandbox Code Playgroud)

原答案:

用于combn获取组合以及反转每个组合。
然后将结果转换data.frame为a。table

tab <- lapply(myList, \(x) combn(x, m=2, FUN=\(cm) rbind(cm, rev(cm)), simplify=FALSE))
tab <- data.frame(do.call(rbind, unlist(tab, rec=FALSE)))
table(tab)

#   X2
#X1  1 2 3 4 5 6 7 8
#  1 0 3 1 2 2 0 1 1
#  2 3 0 1 3 2 1 1 1
#  3 1 1 0 1 0 0 0 0
#  4 2 3 1 0 1 1 0 1
#  5 2 2 0 1 0 0 1 1
#  6 0 1 0 1 0 0 0 0
#  7 1 1 0 0 1 0 0 0
#  8 1 1 0 1 1 0 0 0
Run Code Online (Sandbox Code Playgroud)


akr*_*run 8

我们可以循环list,获取 的成对组合combnstack将其转换为两列数据集,将“值”列转换为factor指定levels为 1 到 8,获取频率计数 ( table),执行叉积 ( crossprod),转换输出回到逻辑,然后逐Reduce元素list相加,最后将diag所有元素赋值为 0。(如果需要,将names的属性设置dimnames为 NULL

out <- Reduce(`+`, lapply(myList, function(x) 
        crossprod(table(transform(stack(setNames(
          combn(x,
         2, simplify = FALSE), combn(x, 2, paste, collapse="_"))), 
          values = factor(values, levels = 1:8))[2:1]))> 0))
diag(out) <- 0
names(dimnames(out)) <- NULL
Run Code Online (Sandbox Code Playgroud)

-输出

> out
  1 2 3 4 5 6 7 8
1 0 3 1 2 2 0 1 1
2 3 0 1 3 2 1 1 1
3 1 1 0 1 0 0 0 0
4 2 3 1 0 1 1 0 1
5 2 2 0 1 0 0 1 1
6 0 1 0 1 0 0 0 0
7 1 1 0 0 1 0 0 0
8 1 1 0 1 1 0 0 0
Run Code Online (Sandbox Code Playgroud)

  • 请参阅问题评论:`tcrossprod` 比这个快 300 倍。 (3认同)