Rotate the matrix into a pair list using apply in R?

I have a matrix similar to the one below, but more.

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 

Ultimately, I need a matrix or data.frame, where every time a call in a row matters, I get the name rowname, the name of the column. So, given the matrix above, I end up with a matrix or data frame below:

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

I can do this with loops and with expand.grid, but this is similar to what I have to do with apply functions. For example, I can get part of the path as follows:

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

which gives me

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

If this is easy, can I also include the number in the cell (for cells over 0) as the third column?

+5
source share
4 answers

igraph approach

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

graph_from_adjacency_matrix() takes the matrix as input and returns a graph. Use weighted=TRUE to return nonzero values ​​as weights. as_data_frame returns an edgelist with associated attributes (in this case, weights)

So for your example

 as_data_frame(graph_from_adjacency_matrix(M, weighted = TRUE)) # from to weight # 1 AB 1 # 2 AC 1 # 3 BC 1 # 4 BD 1 # 5 CA 1 # 6 DB 1 # 7 DC 1 
+4
source

Picking up @Frank's suggestion about melt , one approach and dplyr are used here:

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

The order of the results is different from what you showed, but it is not clear to me whether this matters to you.

+3
source

You do not have to use the apply() loop. Here's an idea in the R base, which uses which() to find the appropriate indexes, and then does some simple extraction and merging.

 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" 

Alternatively, you can use row and col instead of 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
source
 library(tidyr) M = as.data.frame(M) M["rowid"] = row.names(M) gather(M, colid, value, -rowid) 
+2
source

Source: https://habr.com/ru/post/1258761/


All Articles