【问题标题】:R Convert the Dataframe to Matrix based on Certain ColumnsR根据某些列将数据框转换为矩阵
【发布时间】:2021-05-18 03:20:52
【问题描述】:

我的数据如下所示:

ID  Group1  Group2  Group3  Group4  Group5
1   1       0       2       0       3
2   0       0       3       0       2
3   0       0       0       0       1
4   0       3       1       1       0

我想把上面的数据框转换成一个矩阵,ID列作为矩阵的行和列标题。如果两个 ID 属于同一个组(无论 group 列中的值如何),则矩阵中的单元格将为 1。如果两个 ID 属于两个相同的组,则矩阵中的单元格将为 2。基本上,矩阵将如下所示:

  1 2 3 4
1 0 2 1 1
2 2 0 1 1
3 1 1 0 0
4 1 1 0 0

【问题讨论】:

    标签: r dataframe


    【解决方案1】:

    删除 ID 列,将其转换为逻辑矩阵,使用 tcrossprod 将其乘以它的转置(这也将 TRUE/FALSE 值强制为 1/0)并通过乘以 1 减去单位矩阵将其对角线归零.

    tcrossprod(DF[-1] > 0) * (1 - diag(nrow(DF)))
    

    给予:

         [,1] [,2] [,3] [,4]
    [1,]    0    2    1    1
    [2,]    2    0    1    1
    [3,]    1    1    0    0
    [4,]    1    1    0    0
    

    这种变化也适用:

    diag<-`(tcrossprod(DF[-1] > 0), 0)
    

    注意

    Lines <- "ID  Group1  Group2  Group3  Group4  Group5
    1   1       0       2       0       3
    2   0       0       3       0       2
    3   0       0       0       0       1
    4   0       3       1       1       0"
    DF <- read.table(text = Lines, header = TRUE)
    

    【讨论】:

    • 仍然支持你的代码哈哈。抱歉没看过
    【解决方案2】:

    您可以编写一个函数来计算有多少非零值出现在两行之间的同一位置。使用outer 为每个行组合计算它。

    calc_values <- function(x, y) sum(df[x, -1] != 0 & df[y, -1] != 0)
    
    nr <- seq(nrow(df))
    mat <- outer(nr, nr, Vectorize(calc_values))
    diag(mat) <- 0
    dimnames(mat) <- list(df$ID, df$ID)
    mat
    
    #  1 2 3 4
    #1 0 2 1 1
    #2 2 0 1 1
    #3 1 1 0 0
    #4 1 1 0 0
    

    数据

    df <- structure(list(ID = 1:4, Group1 = c(1L, 0L, 0L, 0L), Group2 = c(0L, 
    0L, 0L, 3L), Group3 = c(2L, 3L, 0L, 1L), Group4 = c(0L, 0L, 0L, 
    1L), Group5 = 3:0), class = "data.frame", row.names = c(NA, -4L))
    

    【讨论】:

      【解决方案3】:

      这是一个使用 for 循环和乘以行的逻辑向量的解决方案:

      a <- structure(c(1, 0, 0, 0, 0, 0, 0, 3, 2, 3, 0, 1, 0, 0, 0, 1, 3,
      2, 1, 0), .Dim = 4:5, .Dimnames = list(NULL, c("g1", "g2", "g3",
      "g4", "g5")))
      
      b <- matrix(nrow = nrow(a), ncol = nrow(a))
      
      for (i in 1:nrow(a)) {
        for (j in 1:nrow(a)){
          if(i == j) b[i, j] <- 0
          else b[i, j] <- sum((a[i, ] > 0) * (a[j, ] > 0))
        }
      }
      
      b
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-25
        • 1970-01-01
        • 2018-10-06
        • 2012-05-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多