【问题标题】:Turn matrix into a paired list using apply in R?使用 R 中的应用将矩阵转换为配对列表?
【发布时间】:2016-10-25 16:25:48
【问题描述】:

我有一个类似于下面的矩阵,但更大。

vec <- c(0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0)
M <- matrix(vec, nrow = 4, byrow = TRUE)
colnames(M) <- rownames(M) <- LETTERS[1:4]

   A, B, C, D
A, 0, 1, 1, 0
B, 0, 0, 1, 1
C, 1, 0, 0, 0
D, 0, 1, 1, 0

最终,我想要一个矩阵或一个 data.frame,其中每次连续调用都有一个值,我最终得到一个行名、列名对。所以,给定上面的矩阵,我最终得到下面的矩阵或数据框:

A,B
A,C
B,C
B,D
C,A
D,B
D,C

我可以用循环和 expand.grid 来做到这一点,但这似乎是我应该能够用应用函数来做的事情。例如,我可以像这样到达那里:

tmp <- apply(M, 1, function(x) colnames(M)[which(x > 0)])

这给了我

$A
[1] "B" "C"
$B
[1] "C" "D"
$C
[1] "A"
$D
[1] "B" "C"

如果这很容易,那么我是否也可以将单元格中的数字(对于大于 0 的单元格)作为第三列包含在内?

【问题讨论】:

    标签: r matrix apply


    【解决方案1】:

    igraph 方法

    library(igraph)  
    as_data_frame(graph_from_adjacency_matrix(M, weighted = TRUE))
    

    graph_from_adjacency_matrix() 将矩阵作为输入并返回一个图形。使用weighted=TRUE 将非零值作为权重返回。 as_data_frame 返回带有关联属性(在本例中为权重)的边缘列表

    所以对于你的例子,

    as_data_frame(graph_from_adjacency_matrix(M, weighted = TRUE))
    #   from to weight
    # 1    A  B      1
    # 2    A  C      1
    # 3    B  C      1
    # 4    B  D      1
    # 5    C  A      1
    # 6    D  B      1
    # 7    D  C      1
    

    【讨论】:

      【解决方案2】:

      您不一定需要使用apply() 循环。这是base R中的一个想法,它使用which()找到相关索引,然后进行一些简单的提取和组合。

      wM <- which(M > 0, arr.ind = TRUE)
      matrix(sort(paste(rownames(wM), colnames(M)[wM[,2]], sep = ",")))
      #      [,1] 
      # [1,] "A,B"
      # [2,] "A,C"
      # [3,] "B,C"
      # [4,] "B,D"
      # [5,] "C,A"
      # [6,] "D,B"
      # [7,] "D,C"
      

      或者,您可以使用rowcol 代替which

      M0 <- M > 0
      paste(rownames(M)[row(M)[M0]], colnames(M)[col(M)[M0]], sep = ",")
      # [1] "C,A" "A,B" "D,B" "A,C" "B,C" "D,C" "B,D"
      

      【讨论】:

        【解决方案3】:

        接受@Frank 关于melt 的建议,这是使用该方法的一种方法,dplyr

        library(reshape2)
        library(dplyr)
        
        M2 <- M %>%
          melt(.) %>%
          transmute(pair = paste(Var1, Var2, sep = ","),
                    value = value) %>%
          filter(value > 0)
        

        结果的顺序与您显示的不同,但我不清楚这对您是否重要。

        【讨论】:

          【解决方案4】:
          library(tidyr)
          M = as.data.frame(M)
          M["rowid"] = row.names(M)
          gather(M, colid, value, -rowid)
          

          【讨论】:

            猜你喜欢
            • 2015-05-27
            • 1970-01-01
            • 2015-04-27
            • 2014-05-15
            • 1970-01-01
            • 1970-01-01
            • 2015-07-24
            • 2017-03-22
            • 2017-12-22
            相关资源
            最近更新 更多