1

有没有一种优雅的方法来转换 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
  )
)

到一个层次图对象,例如可以生成一个桑基图?热衷于避免可怕的递归破解是可能的。

如果有帮助,可以以另一种方式合并叶值(本例中的百分比)。提前致谢。


编辑。示例 sankey 来说明图结构

示例桑基图

4

1 回答 1

0

这种可怕的递归方法:

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)

在此处输入图像描述

于 2020-03-22T20:35:14.637 回答