【发布时间】:2017-05-25 05:56:22
【问题描述】:
假设我想根据一些特定的标准修剪一棵由 R 中嵌套列表的层次结构组成的树。我可以使用lapply 足够“轻松”地做到这一点:
# Based an example from the NetworkD3 documentation
# https://christophergandrud.github.io/networkD3/
URL <- paste0(
"https://cdn.rawgit.com/christophergandrud/networkD3/",
"master/JSONdata//flare.json")
flare <- jsonlite::fromJSON(URL, simplifyDataFrame = FALSE)
# Leaf nodes have a "size" attribute. Let's say we want to
# prune all the nodes with size < 5000.
prune <- function(tree) {
if ("children" %in% names(tree)) {
p <- lapply(tree$children, prune)
pp <- p[!unlist(lapply(p, is.null))]
copied_tree = list()
copied_tree$name = tree$name
copied_tree$children = pp
return(copied_tree)
} else if (tree$size < 5000) {
return(NULL)
}
return(tree)
}
pruned <- prune(flare)
在 R for Data Science 中,Hadley Wickham discusses 在许多场景中,purrr 可以替换 apply 系列函数来处理分层数据。但是,这些示例似乎处理单个嵌套列表,或者处理深度嵌套列表的特定节点。
有没有办法使用purrr 来完成上述递归任务?
【问题讨论】:
-
也许我之前的这个尝试是相关的? stackoverflow.com/a/39869503/6197649
-
问题是我想保留树结构,除了修剪。我想过创建一个分隔的节点路径(如 xpath),然后展平,最后重建层次结构,但这似乎比仅使用 lapply 更难,更不优雅。
-
purrr::map是lapply的替代品(带有一些附加功能),但它不会真正改变您在这里所做的事情。您可以查看rapply,它是递归的,但要正确工作可能有点挑剔。 -
@alistaire 是对的,我的回答确实解决了问题的
purrr部分,而不是“递归”部分。我认为这是设计使purrr缺少这样的递归功能,因为“安全”问题 -
参见blog.rstudio.org/2016/01/06/purrr-0-2-0,Hadley 说:“Base R 有 unlist(),但它很危险,因为它总是成功”。我认为它也适用于
rapply()。我看看我能不能想到一个rapply()解决方案...
标签: r recursion purrr tidyverse