Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I add a data frame as vertex attributes with matching ids in igraph?

Tags:

r

igraph

In R, I have a weighted undirected graph as an igraph object :

IGRAPH e7a8fac UNW- 306 2829 -- 
+ attr: name (v/c), label (v/c), nom (v/c), sigle (v/c), statut (v/c), champ (v/c), cp (v/c), info (v/c),  weight (e/n)
+ edges from e7a8fac (vertex names):
 [1] 3 --9  7 --13 7 --15 13--15 11--16 15--17 6 --18 13--20 15--20 20--21 6 --25 18--25 6 --28 10--28 15--28 17--28 18--28 20--28 25--28
[20] 23--30 15--31 17--31 28--31 6 --33 17--33 18--33 22--33 25--33 28--33 7 --34 13--34 15--34 17--34 16--35 34--36 15--37 18--37 20--37
[39] 25--37 28--37 13--43 17--43 18--43 25--43 28--43 33--43 34--43 11--44 13--44 20--44 23--44 30--44 31--44 34--44 40--45 13--47 43--47
[58] 44--47 13--48 15--48 16--48 17--48 20--48 28--48 31--48 34--48 37--48 44--48 45--48 21--54 13--58 34--58 44--58 48--58 10--61 15--61
+ ... omitted several edges

I use another package (tnet) to calculate several indicators. At the end, I have a data frame with 4 columns :

     id degree strength degree_alpha
[1,]  1      0  0.00000     0.000000
[2,]  2      2  3.00000     2.449490
[3,]  3      1  2.00000     1.414214
[4,]  4      1  2.00000     1.414214
[5,]  5      0  0.00000     0.000000
[6,]  6     25 19.10897    21.856906

I would like to add the three columns (degree, strength, degree_alpha) as vertex attributes with matching ids (column id in the data frame, attribute name in igraph).

Igraph set_vertex_attr seems to be the tool to use, but I can't figure out how to make it go through a data frame and only add attributes to existing nodes.

like image 945
mhr Avatar asked Apr 09 '18 08:04

mhr


1 Answers

For me, I think the easiest way to do this is to:

  1. convert the graph into node and edge lists using igraph::as_data_frame
    • You'll actually get a list of data frames if you enter the parameter what = 'both'
  2. merge the data to the node list
  3. recreate the graph using the updated node list and edge list using graph_from_data_frame

.

library(dplyr)

g <- make_graph('zachary') %>%
  set_edge_attr(., 'weight', value = runif(ecount(.), 1, 10)) %>%
  set_vertex_attr(., 'name', value = V(.) %>% as.numeric)

fake_data <- tibble(
  id = V(g) %>% as.numeric(),
  degree = degree(g),
  strength = strength(g)
)

df <- igraph::as_data_frame(g, 'both')

df$vertices <- df$vertices %>% 
  left_join(fake_data, c('name'='id'))

updated_g <- graph_from_data_frame(df$edges,
                                   directed = F,
                                   vertices = df$vertices)

If you don't want to convert back and forth from data formats, then yes, you can use set_vertex_attr.

  1. Iterate through the vector of vertices V(g)
    • You can't iterate the vector of vertices, you'll need to iterate through a vertex attribute that all the vertices have.
  2. Filter the data frame down to the row that matches each vector
  3. Return the value of interest

.

updated_g2 <- g %>%
  set_vertex_attr(., 
                  name = 'degree', 
                  index = V(g), 
                  value = sapply(V(g)$name, function(x){
                    fake_data %>%
                      filter(id == x) %>%
                      .$degree
                    })) %>%
  set_vertex_attr(., 
                  name = 'strength', 
                  index = V(g), 
                  value = sapply(V(g)$name, function(x){
                    fake_data %>%
                      filter(id == x) %>%
                      .$strength
                    }))
like image 109
struggles Avatar answered Nov 18 '22 12:11

struggles