6

It should be very simple, but I am stuck in this operation. I am interested in extracting the block Edge Data: 23,502 x 3. And to indicate the names of the nodes. In short, I need to know the weight of each pair of nodes by their names.

Code:

# A tbl_graph: 11539 nodes and 23502 edges
#
# An undirected simple graph with 2493 components
#
# Node Data: 11,539 x 3 (active)
  name            neighbors groups
  <chr>               <dbl>  <int>
1 CHANSATITPORN N         1   1540
2 POBKEEREE V             1   1540
3 SAINIS G                4    361
4 HARITOS G               4    361
5 KRIEMADIS T             4    361
6 PAPASOLOMOU I           3    361
# … with 11,533 more rows
#
# Edge Data: 23,502 x 3
   from    to weight
  <int> <int>  <dbl>
1     1     2      1
2     3     4      2
3     3     5      2
# … with 23,499 more rows
camille
  • 16,432
  • 18
  • 38
  • 60
majesus
  • 303
  • 2
  • 9

3 Answers3

8

You can extract the edge information using data.frame() on just the edges. You can replace the example tidygraph object I've named tg with your tidygraph object name and the code below should work for you.

library(igraph)
library(tidygraph)
library(tibble)

# https://tidygraph.data-imaginist.com/reference/tbl_graph.html
rstat_nodes <- data.frame(name = c("Hadley", "David", "Romain", "Julia"))
rstat_edges <- data.frame(from = c(1, 1, 1, 2, 3, 3, 4, 4, 4),
                          to = c(2, 3, 4, 1, 1, 2, 1, 2, 3),
                          weight = c(1:9))
tg <- tbl_graph(nodes = rstat_nodes, edges = rstat_edges)
tg
#> # A tbl_graph: 4 nodes and 9 edges
#> #
#> # A directed simple graph with 1 component
#> #
#> # Node Data: 4 x 1 (active)
#>   name  
#>   <fct> 
#> 1 Hadley
#> 2 David 
#> 3 Romain
#> 4 Julia 
#> #
#> # Edge Data: 9 x 3
#>    from    to weight
#>   <int> <int>  <int>
#> 1     1     2      1
#> 2     1     3      2
#> 3     1     4      3
#> # ... with 6 more rows


# Get edge information ----
edge_list <-
  tg %>%
  activate(edges) %>%
  data.frame()
edge_list
#>   from to weight
#> 1    1  2      1
#> 2    1  3      2
#> 3    1  4      3
#> 4    2  1      4
#> 5    3  1      5
#> 6    3  2      6
#> 7    4  1      7
#> 8    4  2      8
#> 9    4  3      9

But if you also want the names in there as well, here is some code to simply extract the node information as well and join in the data together.

# Separate out edges and node data frames
tg_nodes <-
  tg %>%
  activate(nodes) %>%
  data.frame() %>%
  rownames_to_column("rowid") %>%
  mutate(rowid = as.integer(rowid))
tg_edges <-
  tg %>%
  activate(edges) %>%
  data.frame()

named_edge_list <-
  tg_edges %>%
  # Rename from nodes
  left_join(tg_nodes, by = c("from" = "rowid")) %>%
  select(-from) %>%  # Remove unneeded column
  rename(from = name) %>%  # Rename column with names now
  
  # Rename to nodes
  left_join(tg_nodes, by = c("to" = "rowid")) %>%
  select(-to) %>%  # Remove unneeded column
  rename(to = name) %>%  # Rename column with names now

  # Cleaning up
  select(from, to, weight)


named_edge_list
#>     from     to weight
#> 1 Hadley  David      1
#> 2 Hadley Romain      2
#> 3 Hadley  Julia      3
#> 4  David Hadley      4
#> 5 Romain Hadley      5
#> 6 Romain  David      6
#> 7  Julia Hadley      7
#> 8  Julia  David      8
#> 9  Julia Romain      9

Created on 2020-09-21 by the reprex package (v0.3.0)

Eric Leung
  • 2,354
  • 12
  • 25
6

Extracting the edges and then joining with the nodes to get the name as in the accepted answer is intuitive but requires a lot of steps.

The approach using igraph::get.edgelist (second answer) loses additional information stored in edges (in the question: weight).

Here's a solution that should work.

your_tbl_graph %>% 
  activate(edges) %>% 
  mutate(to_name = .N()$name[to], 
         from_name = .N()$name[from]) %>% 
  as_tibble() %>% 
  select(from = from_name, to = to_name, weight)
Martin
  • 1,141
  • 14
  • 24
  • This is so great! You can also use `%E>%` to shorten this even more instead of doing `activate(edges)`. So it would look like `your_tbl_graph %E>% mutate(...)` – mfg3z0 Jul 27 '23 at 15:20
0

Load package igraph() and apply the function get.edgelist() to the activated edges set. To get a proper output, also apply data.frame() subsequently. You'll get the named edgelist.

library(igraph)
edge_list <-
tg %>%
activate(edges) %>%
get.edgelist() %>%
data.frame()
  • Hi Tom, I found this approach really useful but noted that you lose the attributes of the edges with `get.edgelist()`. But, if you add an extra `%>%` with `cbind(weight = get.edge.attribute(tg, 'weight'))` then I think you arrive to the right answer! – loreabad6 Feb 03 '21 at 14:34
  • Thanks, happy to help! Yes, alternatively, you can also simply export the entire edges data.frame with tg %>% activate(edges) %>% as_tibble() and simply cbind() it to the data.frame obtained with get.edgelist(). That way, you'll get all edge attributes in case there are multiple. – Tom Broekel Feb 04 '21 at 15:24