Список в иерархический график - PullRequest
1 голос
/ 22 марта 2020

Существует ли элегантный способ преобразования списка R, такого как ..

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
  )
)

, в объект иерархического графа, который может, например, создать график Санки? Стремление избежать отвратительного рекурсивного взлома возможно.

Листовые значения (проценты в этом примере) могут быть включены альтернативным способом, если это поможет. Заранее спасибо.


Редактировать. Пример санки для иллюстрации структуры графа

example sankey plot

1 Ответ

0 голосов
/ 22 марта 2020

Этот отвратительный рекурсивный подход:

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

...