Return nested list with nested level and value

后端 未结 2 776
灰色年华
灰色年华 2021-01-05 07:10

I would like to visualize some deeply nested data using networkD3. I can\'t figure out how to get the data into the right format before sending to rad

2条回答
  •  傲寒
    傲寒 (楼主)
    2021-01-05 07:58

    As a preface, your data is difficult to work with because critical information is encoded in the order of the values in level. I don't know how you get those values in that order, but consider that there may be a better way to structure that information in the first place, which would make the next task easier.

    Here's a base-y way of converting your data into a data frame with 2 columns, parent and child, then passing that into data.tree functions that can easily convert to the JSON format you need... and then pass it on to radialNetwork...

    level <- c(1, 2, 3, 4, 4, 3, 4, 4, 1, 2, 3)
    value <- letters[1:11]
    
    library(data.tree)
    library(networkD3)
    
    parent_idx <- sapply(1:length(level), function(n) rev(which(level[1:n] < level[n]))[1])
    df <- data.frame(parent = value[parent_idx], child = value, stringsAsFactors = F)
    df$parent[is.na(df$parent)] <- ""
    
    list <- ToListExplicit(FromDataFrameNetwork(df), unname = T)
    radialNetwork(list)
    

    Here's a tidyverse way of achieving the same...

    level <- c(1, 2, 3, 4, 4, 3, 4, 4, 1, 2, 3)
    value <- letters[1:11]
    
    library(tidyverse)
    library(data.tree)
    library(networkD3)
    
    data.frame(level, value, stringsAsFactors = F) %>%
      mutate(row = row_number()) %>%
      mutate(level2 = level, value2 = value) %>%
      spread(level2, value2) %>%
      mutate(`0` = "") %>%
      arrange(row) %>%
      fill(-level, -value, -row) %>%
      gather(parent_level, parent, -level, -value, -row) %>%
      filter(parent_level == level - 1) %>%
      arrange(row) %>%
      select(parent, child = value) %>%
      data.tree::FromDataFrameNetwork() %>%
      data.tree::ToListExplicit(unname = TRUE) %>%
      radialNetwork()
    

    and for a bonus, the current dev version of networkD3 (v0.4.9000) has a new treeNetwork function that takes a data frame with nodeId and parentId columns/variables, which eliminates the need for the data.tree fucntions to convert to JSON, so something like this works...

    level <- c(1, 2, 3, 4, 4, 3, 4, 4, 1, 2, 3)
    value <- letters[1:11]
    
    library(tidyverse)
    library(networkD3)
    
    data.frame(level, value, stringsAsFactors = F) %>%
      mutate(row = row_number()) %>%
      mutate(level2 = level, value2 = value) %>%
      spread(level2, value2) %>%
      mutate(`0` = "root") %>%
      arrange(row) %>%
      fill(-level, -value, -row) %>%
      gather(parent_level, parent, -level, -value, -row) %>%
      filter(parent_level == level - 1) %>%
      arrange(row) %>%
      select(nodeId = value, parentId = parent) %>%
      rbind(data.frame(nodeId = "root", parentId = NA)) %>% 
      mutate(name = nodeId) %>% 
      treeNetwork(direction = "radial")
    

提交回复
热议问题