首页 > 解决方案 > 遍历所有 df 列对并计算非零交叉点

问题描述

我有一个 ~15000*1000 数据框,其中每一列代表一个人,每一行代表一个特征的发生率(0 或 1)。

我想有效地比较所有列对,并为所有可能的对生成所有相互特征(行名)的逗号分隔列表。

目前,我正在通过combn循环遍历所有列,并将相互的行名粘贴到一个字符串中。也就是说我有一个解决方案,但是,它非常非常慢(可能与列数成二次方)。

有没有办法用 tidyr/dplyr 等来矢量化这个问题/解决它?我似乎找不到方法。

例如:

------|individual1 | individual2 | individual3 | ...
trait1|     0      |     1       |      1      | ...
trait2|     0      |     0       |      0      | ...
trait3|     1      |     1       |      1      | ...
 ...  |    ...     |    ...      |     ...     | ... 

trait1,trait3产生对individual 2和的字符串individual 3

谢谢!


玩具数据(实际数据太稀疏,无法提取子集):

df <- data.frame(trait = c("a", "b", "c", "d", "e"), ind1 = c(0, 1, 1, 0, 1), ind2 = c(1, 0, 1, 0, 1), ind3 = c(1, 0, 1, 1, 1))

标签: rdataframedplyrtidyr

解决方案


尝试对每个列组合应用自定义函数。也许效率可以提高一点。

t(combn(1:(ncol(df)-1), 2, function(x){
  string <- paste(df$trait[df[[x[1]+1]] == 1 & df[[x[2]+1]] == 1], collapse = ",")
  c(names(df)[x+1], string)
}))

#      [,1]    [,2]      [,3]   
# [1,] "Alice" "Bob"     "c,e"  
# [2,] "Alice" "Charlie" "c,e"  
# [3,] "Bob"   "Charlie" "a,c,e"

数据

df <- data.frame(trait = c("a", "b", "c", "d", "e"),
                 Alice = c(0, 1, 1, 0, 1),
                 Bob = c(1, 0, 1, 0, 1),
                 Charlie = c(1, 0, 1, 1, 1))

推荐阅读