【问题标题】:Create a matrix symmetric from long table in r从r中的长表创建一个对称矩阵
【发布时间】:2021-01-25 09:52:17
【问题描述】:

这是我的数据

df <- data.frame (Var1  <- c("a", "b", "c","d","e","b","c","d","e","c","d","e","d","e","e"),
                  Var2 <- c("a","a","a","a","a","b","b","b","b","c","c","c","d","d","e")
                  pre <- c(1,2,3,4,5,1,6,7,8,1,9,10,1,11,1) )

我想构建一个以var1和var2函数作为rownames和colnames的对称矩阵,矩阵值是r中“pre”中的对应数字,如下所示:

  a b c d e 
a 1 2 3 4 5
b 2 1 6 7 8 
c 3 6 1 9 10
d 4 7 9 1 11
e 5 8 10 11 1

这个貌似很简单的问题,但是google了很多帖子都没有解决,所以特地来问一下,谢谢!

梦影

【问题讨论】:

    标签: r


    【解决方案1】:

    您可以先获取宽格式的数据。

    library(dplyr)
    library(tidyr)
    
    mat <- df %>%
      pivot_wider(names_from = Var2, values_from = pre, values_fill = 0) %>%
      column_to_rownames('Var1') %>%
      as.matrix()
    
    mat
    #  a b  c  d e
    #a 1 0  0  0 0
    #b 2 1  0  0 0
    #c 3 6  1  0 0
    #d 4 7  9  1 0
    #e 5 8 10 11 1
    

    由于您有一个对称矩阵,您可以将下三角矩阵复制到上三角。

    mat[upper.tri(mat)] <- t(mat)[upper.tri(mat)]
    mat
    
    #  a b  c  d  e
    #a 1 2  3  4  5
    #b 2 1  6  7  8
    #c 3 6  1  9 10
    #d 4 7  9  1 11
    #e 5 8 10 11  1
    

    数据

    df <- data.frame (Var1  = c("a", "b", "c","d","e","b","c","d","e","c","d","e","d","e","e"),
                      Var2 = c("a","a","a","a","a","b","b","b","b","c","c","c","d","d","e"),
                      pre = c(1,2,3,4,5,1,6,7,8,1,9,10,1,11,1) )
    

    【讨论】:

    • 谢谢!不过我觉得这个也需要加上“library('tibble')”,否则我的情况下运行“column_to_rownames”会报错。
    【解决方案2】:

    这是igraph 包的一个选项

    g <- graph_from_data_frame(df,directed = FALSE)
    E(g)$pre <- df$pre
    get.adjacency(g,attr = "pre")
    

    给了

      a b  c  d  e
    a 1 2  3  4  5
    b 2 1  6  7  8
    c 3 6  1  9 10
    d 4 7  9  1 11
    e 5 8 10 11  1
    

    【讨论】:

      【解决方案3】:

      Base R 解决方案(使用 Ronak 提供的数据):

      # Crosstab: 
      mdat <- as.data.frame.matrix(xtabs(pre ~ Var1 + Var2, df))
      
      # Reflect on the diag (thanks @Ronak Shah):
      mdat[upper.tri(mdat)] <- t(mdat)[upper.tri(mdat)]
      

      正如@ThomasIsCoding 指出的那样,我们也可以使用这个单线:

      xtabs(pre ~ ., unique(rbind(df, cbind(setNames(rev(df[-3]), names(df)[-3]), df[3] ))))
      

      正如@thelatemail 指出的那样,我们还可以:

      xtabs(pre ~ ., unique(data.frame(Map(c, df, df[c(2,1,3)]))))
      

      【讨论】:

      • 你也可以试试单行xtabs(pre ~ ., unique(rbind(df, cbind(setNames(rev(df[-3]), names(df)[-3]), df[3] ))))
      • @ThomasIsCoding - 变体 #2 - xtabs(pre ~ ., unique(data.frame(Map(c, df, df[c(2,1,3)])))) 以避免重命名要求
      • @ThomasIsCoding 您的解决方案总是一流的 (Y),base-R 知识首屈一指。
      • @thelatemail 好主意!
      • @thelatemail 非凡
      【解决方案4】:

      这是一个基本的 R 版本:

      df <- data.frame (Var1  = c("a", "b", "c","d","e","b","c","d","e","c","d","e","d","e","e"),
                        Var2 = c("a","a","a","a","a","b","b","b","b","c","c","c","d","d","e"),
                        pre = c(1,2,3,4,5,1,6,7,8,1,9,10,1,11,1))
      
      # Generate new matrix/data frame
      mat2 <- matrix(0, length(unique(df$Var1)), length(unique(df$Var2)))
      
      # Name the columns and rows so we can access values
      rownames(mat2) <- unique(df$Var1)
      colnames(mat2) <- unique(df$Var2)
      
      # Save values into appropriate places into data frame
      mat2[as.matrix(df[, 1:2])] <- as.matrix(df[, 3])
      
      # Using upper triangle trick from @Ronak Shah's answer
      mat2[upper.tri(mat)] <- t(mat2)[upper.tri(mat2)]
      
      # See results
      mat2
      #   a b  c  d  e
      # a 1 2  3  4  5
      # b 2 1  6  7  8
      # c 3 6  1  9 10
      # d 4 7  9  1 11
      # e 5 8 10 11  1
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-04-01
        • 2011-08-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-13
        • 1970-01-01
        • 2019-09-04
        相关资源
        最近更新 更多