Reputation: 618
igraph has two useful functions, shortest_paths
and all_shortest_paths
. The former outputs one of the shortest paths, the other outputs all of them. However, the former also is able to output the edge types of the path while the latter doesn't seem to be able to.
How do I use all_shortest_paths
to extract the "edge type" for all of the shortest paths? I have provided clarifying code below:
library(igraph)
m <- read.table(row.names=1, header=TRUE, text=
" A B C D
A 0 1 1 0
B 0 0 0 1
C 0 0 0 1
D 0 0 0 0")
m <- as.matrix(m)
ig <- graph.adjacency(m, mode="directed")
plot(ig)
E(ig)
for (i in 1:length(E(ig))) {
if (i == 4) {
E(ig)[i]$type <- -1
} else {
E(ig)[i]$type <- 1
}
}
###This gets one of the shortest paths
test1 <- shortest_paths(ig, from = V(ig)[1], to = V(ig)[4], mode = "out", output = "epath")
###This outputs the types for the shortest path above
test1$epath[[1]]$type
###This gets all the shortest paths
test2 <- all_shortest_paths(ig, from = V(ig)[1], to = V(ig)[4], mode = "out")
###The code below doesn't work. How do I get the types for ALL the shortest paths?
test2$res[[1]]$type
Upvotes: 3
Views: 456
Reputation: 93813
Get the selections of edges and extract the type:
lapply(test2$res, \(x) E(ig)[head(x, -1) %->% tail(x, -1)]$type)
#[[1]]
#[1] 1 -1
#
#[[2]]
#[1] 1 1
See https://igraph.org/r/doc/igraph-es-indexing.html or ?"igraph-es-indexing"
from inside R for all the details on the options of how this works. E.g.:
E(ig)[c("A","B") %->% c("B","D")]
#+ 2/4 edges from 16165ed (vertex names):
#[1] A->B B->D
Upvotes: 1
Reputation: 349
This can be done relatively simply while looping through the test2$res
and using igraph
's accessor function as_ids()
:
suppressMessages(library(igraph))
m <- read.table(row.names=1, header=TRUE, text=
" A B C D
A 0 1 1 0
B 0 0 0 1
C 0 0 0 1
D 0 0 0 0")
m <- as.matrix(m)
ig <- graph.adjacency(m, mode="directed")
plot(ig)
E(ig)
for (i in 1:length(E(ig))) {
if (i == 4) {
E(ig)[i]$type <- "green"
} else {
E(ig)[i]$type <- "red"
}
}
OriginalGraph <- get.data.frame(x = ig)
EdgeTypesPresent <- vector(mode = "list",
length = length(test2))
for (m1 in seq_along(test2$res)) {
p1 <- as_ids(test2$res[[m1]])
EdgeTypesPresent[[m1]] <- unique(OriginalGraph$type[OriginalGraph$from %in% p1 &
OriginalGraph$to %in% p1])
}
This gives us:
> EdgeTypesPresent
[[1]]
[1] "red" "green"
[[2]]
[1] "red"
Upvotes: 1
Reputation: 101247
Try the code below
df <- get.data.frame(ig)
lapply(
test2$res,
function(x) {
nm <- names(x)
merge(
df,
data.frame(from = head(nm, -1), to = tail(nm, -1))
)$type
}
)
and you will get
[[1]]
[1] 1 -1
[[2]]
[1] 1 1
If you want to see more information, you can use
df <- get.data.frame(ig)
lapply(
test2$res,
function(x) {
nm <- names(x)
merge(
df,
data.frame(from = head(nm, -1), to = tail(nm, -1))
)
}
)
and you will get
[[1]]
from to type
1 A C 1
2 C D -1
[[2]]
from to type
1 A B 1
2 B D 1
Upvotes: 2