使用purrr递归处理任意层次结构

3
假设我想要根据特定的标准修剪一个由嵌套列表组成的树形结构,在R中可以使用轻松实现:
# 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数据科学》一书中,Hadley Wickham 讨论了许多场景,其中purrr可以替代apply函数族来处理分层数据。然而,这些例子似乎只涉及单层嵌套列表或深度嵌套列表的特定节点。
是否有一种方法可以使用purrr来完成像上面讨论的递归任务?

也许我之前的尝试是相关的?https://dev59.com/aGsz5IYBdhLWcg3wDjto#39869503 - Aurèle
问题在于我想保留树结构,除了修剪部分。我考虑创建一个定界的节点路径(如xpath),然后展平,最后重建层次结构,但这看起来比只使用lapply更困难和不优雅。 - David Bruce Borenstein
1
purrr::maplapply的替代品(带有一些额外功能),但它并不会真正改变你在这里所做的事情。你可以尝试使用rapply,它是递归的,但可能需要一些技巧才能正确地工作。 - alistaire
@alistaire 是正确的,我的回答确实涉及了问题中的 purrr 部分,而不是“递归”部分。我认为这是 purrr 缺乏递归功能的设计原因,因为存在“安全性”问题。 - Aurèle
请参阅https://blog.rstudio.org/2016/01/06/purrr-0-2-0/,其中Hadley说:“Base R有unlist()函数,但它很危险,因为它总是成功的”。我认为这也适用于rapply()。我将看看是否可以想出一个rapply()解决方案... - Aurèle
1个回答

4
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

这非常优雅(令人印象深刻)!你能告诉我这里的波浪符号是什么作用吗?我对这个符号的使用有些模糊——我知道它在统计模型和ggplot图层中使用,但我不知道它在R中如何解释。 - David Bruce Borenstein
1
谢谢。波浪号在R中是一种多用途的公式语法。在这里,它们被用作匿名函数的快捷方式,.x.y是隐式参数。例如,请参阅purrr自述文件或help(map)~ .x + 1等同于function(.x) .x + 1 - Aurèle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接