问题
given a graph, for example:
require(igraph)
g <- graph.famous("Zachary")
such that some of its properties are:
diameter(g)
[1] 5
> farthest.nodes(g)
[1] 15 17 5
> average.path.length(g)
[1] 2.4082
> path.length.hist(g)
$res
[1] 78 265 137 73 8
$unconnected
[1] 0
As you can see there are 8 paths with length = 5, 73 with length = 4, and so on...
I would like to be able to isolate groups of nodes that are involved in a path of certain length. For example, I would like to know the nodes involve in the 73 paths of length 4, and their connected nodes respectively.
Let me clarify this with one easy example, the diameter of the graph. For this particular case one can do:
##names of the nodes involved in the diameter path of the graph
nodes.diameter<-get.diameter(g)
edges <- as.data.frame(get.edgelist(g))
edges.diameter <- edges[which(edges$V1 %in% nodes.diameter),]
g.diameter <- graph.data.frame(edges.diameter, directed = FALSE)
##some aesthetics for the plot
V(g.diameter)$label.cex <- 1
plot(g.diameter,vertex.size=10)
This is a particular example because is easy to get the node names for the diameter. But, is there a way to get the node names given a certain path length? (naively, something like get.path(g,length = X)
, and in a naive, ideal world this would return a list with the nodes involved in the paths of length = X
. For example, for length = 4
, the list would have length 73 elements each containing the nodes involved in each of the 73 paths of length 4)
many thanks in advance for your time.
回答1:
The path.length.hist
function looks at all possible shortest paths. So these two commands are the same
# path.length.hist(g)$res
[1] 78 265 137 73 8
sp <- shortest.paths(g)
table(sp[upper.tri(sp)])
# 1 2 3 4 5
# 78 265 137 73 8
which means the the information you are after can be extracted from shortest.paths()
. Here's a function that will return the index of the vertices involved in the paths
get_paths_by_length <- function(g, len) {
sp <- shortest.paths(g)
sp[lower.tri(sp,TRUE)] <- NA
wp <- which(sp==len, arr.ind=TRUE)
mapply(function(a,b) get.shortest.paths(g, a, b)$vpath, wp[,1], wp[,2])
}
which returns
get_paths_by_length(g,5)
# [[1]]
# [1] 15 33 3 1 6 17
# [[2]]
# [1] 16 33 3 1 6 17
# [[3]]
# [1] 17 6 1 3 33 19
# [[4]]
# [1] 17 6 1 3 33 21
# [[5]]
# [1] 17 6 1 3 33 23
# [[6]]
# [1] 17 6 1 3 28 24
# [[7]]
# [1] 17 6 1 9 34 27
# [[8]]
# [1] 17 6 1 3 33 30
for the eight paths of length 5.
来源:https://stackoverflow.com/questions/28051862/how-to-select-certain-paths-of-a-graph-based-on-their-length-using-igraph-in-r