R:从字符向量中的ID创建嵌套列表

时间:2016-04-30 23:24:14

标签: r

我有一个像这样的分层ID的字符向量:

ids <- c("0","1","2","3","1.1","1.2","1.3","2.1","2.2","2.11","2.21","2.22")

层次结构如下:

1
    1.1
    1.2
    1.3
2
    2.1
        2.11
    2.2
        2.21
        2.22

我想使用diagonalNetwork()包中的networkD3来可视化此层次结构。但diagonalNetwork()需要一个嵌套列表,定义每个节点的子节点如下:

l <- list(name = "0",
            children = list(
              list(name = "1",
                   children = list(
                     list(name = "1.1"),
                     list(name = "1.2"),
                     list(name = "1.3")
                   )
              ),
              list(name = "2",
                   children = list(
                     list(name = "2.1",
                          children = list(
                            list(name = "2.11")
                          )
                     ),
                     list(name = "2.2",
                          children = list(
                            list(name = "2.21"),
                            list(name = "2.22")
                          )
                     )
                   )
              )
            )
)

我的实际id组更大更深(最多6位数),所以我需要一种方法来自动创建这个嵌套列表。我开始创建一个存储id的数据框架。像这样的几列中的数字:

df <- data.frame(root = 0,
                 a = c( 1, 1, 1, 1, 2, 2, 2, 2, 2, 2),
                 b = c(NA, 1, 2, 3,NA, 1, 1, 2, 2, 2),
                 c = c(NA,NA,NA,NA,NA,NA, 1,NA, 1, 2))

但我无法想到如何进一步解决我的问题。 有没有更有希望的方法?

1 个答案:

答案 0 :(得分:2)

这是一个基于递归函数的可能解决方案。它绝不是一个快速的解决方案,但应该适合你。

library(network3D)
findChildren <- function(pa, ids) {
    lapply(ids, function(ch){
        if(grepl(paste("^", pa, sep = ""), ch) && ch != pa &&
           nchar(gsub("\\.", "", ch)) == nchar(gsub("\\.", "", pa)) + 1) 
        {
            childrenTmp = Filter(Negate(is.null), findChildren(ch, ids))
            if(length(childrenTmp) != 0) list(name = ch, children = childrenTmp)
            else list(name = ch)
        }
    }
    )
}

myList <- list(name = "0",
               children = Filter(
                   function(x){nchar(x$name) == 1 },                    
                   lapply(ids[-1], function(id) {
                       childrenTmp = Filter(Negate(is.null), findChildren(id, ids))
                       if(length(childrenTmp) != 0) list(name = id, children = childrenTmp)
                       else list(name = id)
                   }
                   )
               )
               )
diagonalNetwork(myList)

enter image description here