将节点的路径转换为列表的树形结构列表

问题描述 投票:0回答:1

我有一个 data.frame,其中一列代表节点路径,我想将其转换为一棵树。我有什么简单的功能可以做到这一点吗?

这是一个简单的例子:

data <- data.frame(
  Name = c("A", "A1", "A2", "A1a", "A1b", "A2a", "A2b", "A2c"),
  Path = c("1", "1,1", "1,2", "1,1,1", "1,1,2", "1,2,1", "1,2,2", "1,2,3")
)

我想转变为:


nodes <- list(
  list(
    text = "A",
    li_attr = list(id = "1")
    state = list(opened = TRUE),
    
    children = list(
      list(
        text = "A1",
        li_attr = list(id = "1,1")
        state = list(opened = TRUE),
        
        children = list(
          list(
            text = "A1a",
            li_attr = list(id = "1,1,1")),
          list(
            text = "A1b",
            li_attr = list(id = "1,1,2"))
          )),

        list(
            text = "A2",
            li_attr = list(id = "1,2")
            state = list(opened = TRUE),
            
            children = list(
              list(
                text = "A2a",
                li_attr = list(id = "1,2,1")),
              list(
                text = "A2b",
                li_attr = list(id = "1,2,2")),
              list(
                text = "A2c",
                li_attr = list(id = "1,2,3"))
            
        )
      )
    )
  )
)
r tree
1个回答
0
投票

没有现有的功能可以完全满足您的要求。您必须编写一个递归函数来为您完成此操作:

f <- function(path, name, parent_node = NULL) {
  nodes <- strsplit(path, ',')
  parents <- match(unique(sapply(nodes, `[`, 1)), path)
  lapply(parents, function(i) {
    li <- list(Text = name[i],
         li_attr = list(id = if(is.null(parent_node)) parents[i]
                          else paste(parent_node, parents[i], sep = ',')))
    kids <- sapply(nodes, \(x) x[1] == parents[i])
    if(length(kids) > 0) {
      if(sum(kids) > 1) {
        n <- which(kids & lengths(nodes) > 1)
        li$children <-
        f(sapply(nodes[n], \(x) paste0(x[-1], collapse = ',')), name[n],
          parent_node = li$li_attr$id)
      }
    }
    return(li)
  })
}

我们这样称呼它:

result <- f(data$Path, data$Name)

结果如下所示:

list(
  list(Text = "A", 
       li_attr = list(id = 1L), 
       children = list(

         list(Text = "A1", 
              li_attr = list(id = "1,1"), 
              children = list(
                list(Text = "A1a", 
                     li_attr = list(id = "1,1,1")), 
                list(Text = "A1b", 
                     li_attr = list(id = "1,1,2"))
                )
              ), 

         list(Text = "A2", 
              li_attr = list(id = "1,2"), 
              children = list(
                list(Text = "A2a", 
                     li_attr = list(id = "1,2,1")), 
                list(Text = "A2b", 
                     li_attr = list(id = "1,2,2")), 
                list(Text = "A2c", 
                     li_attr = list(id = "1,2,3"))
                )
              )
       )
  )
)
© www.soinside.com 2019 - 2024. All rights reserved.