I'm trying to identify and count all non-zero pathways starting from a specific node in a network (here N2). Each step through a node is 1, so from N2 to Z3 would be a length of 2. I'd like to extract each possible pathway as rows with node ID in separate columns, and have a count as well. This is the matrix from the above diagram and as far as I got:
mat1 <- read.table(text = "
X1 N1 N2 A2 Z3 M
1 N1 -1 0 -1 0 0
2 N2 0 -1 -1 0 0
3 A2 1 1 0 -1 -1
4 Z3 0 0 1 -1 0
5 M 0 0 1 0 -1
", header = TRUE)
mat1 <- as.matrix(mat1)
nzpath <- which(mat1 != 0, arr.ind = TRUE)
pathways <- data.frame(
row = nzpath[, 1],
column = nzpath[, 2],
value = mat1[nzpath[, 1], nzpath[, 2]])
the desired output example:
out <- read.table(text = "
node1 node2 node3 count
1 N2 A2 Z3 2
", header = TRUE)
You might want to find a less convoluted (removing at least some lapply()
's) solution from
v0
result = local({
l <-
lapply(colnames(mat1), \(v) igraph::all_simple_paths(g, v, mode = "out")) |>
unlist(recursive = FALSE) |>
lapply(\(x) names(x))
n <- lengths(l)
m <- max(n)
l <- lapply(l, `length<-`, m)
data.frame(
do.call("rbind", l) |>
data.frame() |>
setNames(c("from", paste0("to", seq(m-1)))),
count = n - 1,
row.names = NULL
)
})
giving
> result
from to1 to2 count
1 N1 A2 <NA> 1
2 N1 A2 M 2
3 N1 A2 Z3 2
4 N2 A2 <NA> 1
5 N2 A2 M 2
6 N2 A2 Z3 2
7 A2 M <NA> 1
8 A2 Z3 <NA> 1
Corrected input:
mat1 <- matrix(
c(
1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 1,
0, 0, 0, 1, 1,
1, 1, 0, 0, 0
),
nrow = 5, ncol = 5, byrow = TRUE,
dimnames = list(NULL, c("M", "Z3", "N1", "N2", "A2"))
)
g <- igraph::graph_from_adjacency_matrix(mat1, mode = "directed")
One advantage of {base}
+ {igraph}
is that we do not need to care about changes in, say, {tidyverse}
, which has alternatives to the advertised base functions.