将同现数据帧转换为方矩阵

时间:2018-11-14 21:20:16

标签: r

说我有这个数据框:

    d <- structure(list(A = c(1L, 1L, 1L, 0L, 1L, 1L, 1L), B = c(1L, 1L, 
1L, 1L, 1L, 1L, 1L), C = c(0L, 0L, 1L, 0L, 0L, 0L, 0L), D = c(0L, 
0L, 0L, 0L, 0L, 0L, 0L), E = c(0L, 0L, 0L, 0L, 0L, 0L, 0L), F = c(0L, 
0L, 0L, 0L, 0L, 0L, 0L), G = c(0L, 0L, 0L, 0L, 0L, 0L, 0L), H = c(0L, 
1L, 0L, 0L, 1L, 1L, 0L)), row.names = c(NA, -7L), class = c("tbl_df", 
"tbl", "data.frame"))



      A     B     C     D     E     F     G     H
  <int> <int> <int> <int> <int> <int> <int> <int>
1     1     1     0     0     0     0     0     0
2     1     1     0     0     0     0     0     1
3     1     1     1     0     0     0     0     0
4     0     1     0     0     0     0     0     0
5     1     1     0     0     0     0     0     1
6     1     1     0     0     0     0     0     1
7     1     1     0     0     0     0     0     0

我希望将其转换为8x8的方阵(A:H x A:H)。每个单元格等于两个字母一起出现的总次数。例如,单元格[A,B]的值应为6,因为列A和B在7行中都具有6分之一。单元格[B,A]具有相同的值。输出应为:

我可以在这样的循环中这样做:

mat <- matrix(NA,8,8)
for(i in 1:8) { 
  for(j in 1:8) {
    mat[i,j] <- sum(mat1[,i]==1 & mat1[,j]==1)
    mat[j,i] <- sum(mat1[,j]==1 & mat1[,i]==1)
  }}
diag(mat)<-0
rownames(mat)<-colnames(mat)<-LETTERS[1:8]
mat

所需的输出:

  A B C D E F G H
A 0 6 1 0 0 0 0 3
B 6 0 1 0 0 0 0 3
C 1 1 0 0 0 0 0 0
D 0 0 0 0 0 0 0 0
E 0 0 0 0 0 0 0 0
F 0 0 0 0 0 0 0 0
G 0 0 0 0 0 0 0 0
H 3 3 0 0 0 0 0 0

但是当处理非常大的矩阵时,这很慢。有办法更快地做到这一点吗?

1 个答案:

答案 0 :(得分:2)

您用单词描述的内容听起来像是将diag设置为0的普通矩阵乘法:

temp <- t(as.matrix(d)) %*% as.matrix(d)
diag(temp) <- 0


> temp
  A B C D E F G H
A 0 6 1 0 0 0 0 3
B 6 0 1 0 0 0 0 3
C 0 1 0 0 0 0 0 0
D 0 0 0 0 0 0 0 0
E 0 0 0 0 0 0 0 0
F 0 0 0 0 0 0 0 0
G 0 0 0 0 0 0 0 0
H 3 3 0 0 0 0 0 0

tcrossprod函数可能甚至更快,但是这两种方法肯定会胜过嵌套循环。