Search code examples
rigraphnetwork-analysis

igraph spatial distance edge attribute based on edge match?


I'm building a spatial network where edges represent the movement between two locations in real world terms, the weight of edges in the number of times the movement occurred, and the nodes are the points in space.

For instance, consider airports. Where nodes are the airports, and edges are the number of flights between the airports, and each edge has an attribute distance (i.e. km between airports). My hope is to then use the distance in some downstream analyses (not sure if they're going to be useful).

Anyway, I'm not quite sure how to integrate the spatial information into the graph layer (i.e. attributing distance to the edges). Typically, if working in dataframes I would do a join, but given the igraph object structure I'm not sure how to do this. Doing it manually, by setting attributes in the order of the igraph edges is unfeasible given the sheer amount of data I have.

Here is a small reproducible example. In real terms, I calculate edges from large adjacency matrices in which I have rows that represent departures (from) and arrivals are (to). I can calculate distances using coordinates associated to the spatial points at an earlier time, but how do I then integrate everything in igraph?

library(igraph)

g = make_graph(c("Paris", "Amsterdam", "Amsterdam", 
"London", "Milan", "Paris", "Dublin", "London"), directed = TRUE)


g

#> IGRAPH 3c2accf DN-- 5 4 -- 
#> + attr: name (v/c)
#> + edges from 3c2accf (vertex names):
#> [1] Paris    ->Amsterdam Amsterdam->London    Milan    ->Paris    
#> [4] Dublin   ->London

The data from which the edges are created looks like the following. It's in tibble format, then is converted using xtabs into structure needed by igraph to make graph layer.

edges = tibble(from = c("Paris","Amsterdam","Milan","Dublin"), to = c("Amsterdam","London","Paris","London"))

edges = xtabs(~ from + to, edges)

edges
#>            to
#> from        Amsterdam London Paris
#>   Amsterdam         0      1     0
#>   Dublin            0      1     0
#>   Milan             0      0     1
#>   Paris             1      0     0

I'm guessing there is some easy way how to associate specific edges to a specific attribute by matching strings, but just not sure how to do it. Ultimately, all I want to achieve is to have an edge attribute that describes the distance between the two airports in question.

Thank you.


Solution

  • I guess you can use as_adjacency_matrix with attr = enabled, e.g.,

    edges %>%
      mutate(xfrom = c(48.87, 8.87, 45.49, 53.34), yfrom = c(2.30, 2.30, 9.17, -6.26), xto = c(52.36, 51.48, 48.87, 51.48), yto = c(4.87, -0.10, 2.30, -0.10)) %>%
      mutate(distance_km = geosphere::distHaversine(cbind(xfrom, yfrom), cbind(xto, yto)) / 1000) %>%
      select(from, to, distance_km) %>%
      graph_from_data_frame(directed = FALSE) %>%
      as_adjacency_matrix(attr = "distance_km")
    

    and you will obtain

    5 x 5 sparse Matrix of class "dgCMatrix"
                 Paris Amsterdam    Milan  Dublin   London
    Paris       .       481.8386 851.3811   .        .
    Amsterdam 481.8386    .        .        .     4749.576
    Milan     851.3811    .        .        .        .
    Dublin      .         .        .        .      716.185
    London      .      4749.5765   .      716.185    .