使用 purrr 递归处理任意层次结构
Processing arbitrary hierarchies recursively with purrr
假设我想根据某些特定标准修剪由 R 中的嵌套列表层次结构组成的树。我可以 "easily" 使用 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
来完成递归任务,例如上面讨论的任务?
library(purrr)
prune_2 <- function(tree) {
# print(tree$name)
# print(map_lgl(tree$children, ~ "size" %in% names(.x)))
tree$children %<>%
map_if(~ "children" %in% names(.x), prune_2) %>%
discard(~ if ("size" %in% names(.x)) .x$size < 5000 else FALSE)
tree
}
pruned_2 <- prune_2(flare)
identical(pruned, pruned_2)
# [1] TRUE
假设我想根据某些特定标准修剪由 R 中的嵌套列表层次结构组成的树。我可以 "easily" 使用 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
来完成递归任务,例如上面讨论的任务?
library(purrr)
prune_2 <- function(tree) {
# print(tree$name)
# print(map_lgl(tree$children, ~ "size" %in% names(.x)))
tree$children %<>%
map_if(~ "children" %in% names(.x), prune_2) %>%
discard(~ if ("size" %in% names(.x)) .x$size < 5000 else FALSE)
tree
}
pruned_2 <- prune_2(flare)
identical(pruned, pruned_2)
# [1] TRUE