Processing arbitrary hierarchies recursively with purrr

↘锁芯ラ 提交于 2019-12-12 12:58:20

问题


Suppose that I wanted to prune a tree consisting of a hierarchy of nested lists in R, based on some particular criterion. I can do this "easily" enough using 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)

In R for Data Science, Hadley Wickham discusses a number of scenarios in which purrr can replace the apply family of functions for handling hierarchical data. However, these examples seem to deal either with singly nested lists, or with specific nodes of deeply nested lists.

Is there a way to use purrr to accomplish recursive tasks such as the one discussed above?


回答1:


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


来源:https://stackoverflow.com/questions/41573995/processing-arbitrary-hierarchies-recursively-with-purrr

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!