是否存在简洁的dplyr方式实现多次左自连接处理层级数据?
R层级关系数据的动态展开方案
纯tidyverse(dplyr+purrr)动态实现
无需手动编写重复的left_join语句,可自动适配任意深度的层级结构:
library(tidyverse) # 测试数据 test_hierarchie <- tribble(~child, ~parent, "A", "B", "B", "C", "D", "E" ) # 自动计算层级最大深度,确定迭代次数 max_depth <- 0 current_nodes <- test_hierarchie$child while(any(current_nodes %in% test_hierarchie$parent)) { max_depth <- max_depth + 1 current_nodes <- test_hierarchie$parent[test_hierarchie$child %in% current_nodes] } # 动态迭代执行left_join test_hierarchie_transformed <- reduce( 1:max_depth, function(df, i) { join_col <- paste0(c("parent", rep("_grand", i-1)), collapse = "") left_join(df, test_hierarchie, by = setNames("child", join_col), suffix = c("", "_grand")) }, .init = test_hierarchie ) %>% pivot_longer(names_to = "relation", cols = contains("parent"), values_to = "parent") %>% filter(!is.na(parent))
运行结果和你原有手动写join的输出完全一致,relation字段已按笔误修正为_grand后缀。
igraph实现方案(更高效简洁)
针对层级类的关联数据,igraph包的处理逻辑更简洁,性能也更适合大数据量场景:
library(igraph) # 将层级数据转为有向图结构 g <- graph_from_data_frame(test_hierarchie, directed = TRUE) # 批量提取所有子节点的父/祖先节点,整理为目标格式 test_hierarchie_transformed <- map_dfr(unique(V(g)$name), function(node) { ancestors <- all_simple_paths(g, from = node, mode = "out") %>% map(~as.character(.x)) %>% unlist() %>% unique() %>% setdiff(node) if(length(ancestors) == 0) return(tibble()) tibble( child = node, relation = paste0("parent", rep("_grand", seq_along(ancestors)-1)), parent = ancestors ) })
内容的提问来源于stack exchange,提问作者CorneeldH
相关产品推荐
相关产品推荐

