1

Is there an elegant way to convert an R list such as..

x = list(
  `People who` = list(
    `believe in aliens` = list(
      `believe aliens visit/visited Earth` = 5,
      `believe in aliens elsewhere in universe` = 45
    ),
    `do not believe in aliens` = 50
  )
)

to a hierarchical graph object that could e.g. generate a sankey plot? Keen to avoid a hideous recursive hack is possible.

The leaf values (percentages in this example) could be incorporated in an alternative way if it helps. Thanks in advance.


Edit. Example sankey to illustrate graph structure

example sankey plot

geotheory
  • 22,624
  • 29
  • 119
  • 196
  • Do you have an example of what exactly you want? Anything approaches you're taking to get started? – camille Mar 22 '20 at 18:55
  • I hope the sankey above helps to illustrate the graph structure I'm trying to achieve? I've been exploring igraph and tidygraph documentation but nothing obviously helpful. – geotheory Mar 22 '20 at 19:21

1 Answers1

0

That hideous recursive approach:

require(dplyr)
require(purrr)

x = list(
  `believe in aliens` = list(
    n = 50,
    `believe aliens visit/visited Earth` = list(n = 5),
    `believe in aliens elsewhere in universe` = list(n = 45)
  ),
  `do not believe in aliens` = list(n = 50)
)

parse_edge = function(parent_name, lst){
  lst_names = names(lst)[names(lst) != 'n']
  if(length(lst_names) == 0) return(tibble())
  this_edges = map_df(lst_names, ~ tibble(from = parent_name, to = .x, weight = lst[[.x]]$n))
  child_edges = map2_df(lst_names, lst[lst_names], ~ parse_edge(.x, .y))
  bind_rows(this_edges, child_edges)
}

parse_edge('People who', x)
#> # A tibble: 4 x 3
#>   from              to                                      weight
#>   <chr>             <chr>                                    <dbl>
#> 1 People who        believe in aliens                           50
#> 2 People who        do not believe in aliens                    50
#> 3 believe in aliens believe aliens visit/visited Earth           5
#> 4 believe in aliens believe in aliens elsewhere in universe     45

df = parse_edge('People who', x)
g = igraph::graph_from_data_frame(df)

# or..

require(networkD3)
n = as.data.frame(enframe(unique(c(df$from, df$to)), name = NULL, value = 'id'))
e = as.data.frame(df) %>% mutate(from = match(from, n$id)-1, to = match(to, n$id)-1)

sankeyNetwork(Links = e,  Nodes = n,
              Source = 'from', Target = 'to', Value = 'weight', NodeID = 'id',
              units = 'TWh', fontSize = 18, nodeWidth = 30)

enter image description here

geotheory
  • 22,624
  • 29
  • 119
  • 196