0

I would like to go one step further with this question (Find total of second variable related to the distance of route from get.shortest.paths()). How does one get the matrix of distances between nodes, when the 'shortest' path is found using the newcost variable?

(My experience with igraph is very limited).

      df2 = rbind(c(234,235,21.6,75),
      c(234,326,11.0,35),
      c(235,241,14.5,78),
      c(326,241,8.2,98),
      c(241,245,15.3,75),
      c(234,245,38.46,65))

      df2 = as.data.frame(df2)
      names(df2) = c("start_id","end_id","newcost","distance")

      require(igraph)
      g2 <- graph.data.frame(df2, directed=FALSE)
      tmp2 = shortest.paths(g2,weights=E(g2)$newcost)
      tmp2 #this gives the matrix of newcost-weighted shortest distances

Where I could use help is how to find all paths, say using optimal.path <- get.shortest.paths, and using sum(E(g2, path = optimal.path)$distance) to create the matrix of distances

what I would really like is an edgelist of distances for all node pairs, like:

      startid endid shortestdist
      234     235     75
      234     245     208

What is tricky about this problem is that newcost is used to find the shortest paths, but what I want is the sum of another variable - the distance variable on each shortest path between node pairs.

Community
  • 1
  • 1
user2627717
  • 344
  • 3
  • 14
  • So, you want all the data that's in `tmp2`, but you just want it in a different format? Instead of a matrix, you want rows for each start/end combination? – MrFlick May 16 '14 at 21:21
  • @MrFlick: Thanks for asking. What I want is different. The data in tmp2 is the 'newcost' sums, that gives the weighted path lengths. What I want is the sum of the distance variable for the shortest paths. – user2627717 May 16 '14 at 21:28
  • And those just happen to be equal for the two examples you've shown? – MrFlick May 16 '14 at 21:30
  • @MrFlick: the example has now been corrected. Thanks! – user2627717 May 17 '14 at 00:12

1 Answers1

0

Ok, first let me make it clear that I am not an igraph user myself. Nevertheless I thought the question was interesting so I thought I'd take a look. And I too could find no easy solution to the problem you are having. I ended up making some helper functions to make the process possible. There is a good chance that i've re-coded the functionality inside igraph already but I could not find it.

Let me first define get.shortest.paths.for.all which will not just return the shortest path lengths for a given attribute, but will also return the shortest path themselves for all vertices in the graph. Here's that code

get.shortest.paths.for.all<-function(graph, attr) {
    paths<-lapply(1:(vcount(graph)-1), function(i) {
        get.all.shortest.paths(
            graph, 
            weights=get.edge.attribute(g2,attr),
            from = V(graph)[i],
            to = V(graph)[(i+1):vcount(graph)]
        )$res
    })
    unsplit(paths, rep.int(seq_along(paths), sapply(paths, length)))
}

Now let me define get.path.dist.matrix will takes a graph and a list of paths (like the one returned by get.shortest.paths.for.all) and will calculate the distance for a given attribute between each of those paths

get.path.dist.matrix<-function(graph, path, attr) {
    dd<-get.adjacency(graph, attr=attr)
    uniqs <- numeric(0)
    if (is.list(path)) {
        starts<-sapply(path, head, 1)
        ends<-sapply(path, tail, 1)
        uniqs <- unique(sort(c(starts,ends)))
    } else {
        uniqs <- c(head(path,1), tail(path,1))
    }
    m<-matrix(0, nrow=length(uniqs), ncol=length(uniqs),
        dimnames=list(V(graph)$name[uniqs],V(graph)$name[uniqs]))
    for(pp in path) {
        m[pp[1], pp[length(pp)]]<-sum(dd[embed(pp,2)])
    }
    m+t(m)
}

Using your sample data, I use them like this

paths <- get.shortest.paths.for.all(g2, "newcost")
get.path.dist.matrix(g2, paths,"distance")

#     234 235 326 241 245
# 234   0  75  35 133 208
# 235  75   0 176  78 153
# 326  35 176   0  98 173
# 241 133  78  98   0  75
# 245 208 153 173  75   0

Which seems reasonable and distinct from shortest.paths(g2,weights=E(g2)$distance). To try to test my functions, I see that

all(tmp2==get.path.dist.matrix(g2, paths,"newcost"))

So feel free to try these out and let me know if you see any problems or possible improvements.

MrFlick
  • 195,160
  • 17
  • 277
  • 295