R语言层级结构data.frame中查找每行对应根节点root_id的高效实现方案
基于data.table的根节点查询实现
核心思路
无需编写复杂递归逻辑,采用迭代向上溯源的方式实现,循环次数等于数据的最大层级深度,搭配data.table的向量化操作,处理大表性能远优于递归实现。
完整实现代码
library(data.table) # 构造测试数据 DF_in <- data.frame(id = 1:10, parent_id = c(NA, NA, 1:4, 1:4)) setDT(DF_in) # 1. 初始化每个节点的根节点为自身id DF_in[, root_id := id] # 标记需要溯源的非根节点(父节点非NA) need_update <- DF_in[, !is.na(parent_id)] # 2. 迭代向上溯源,直到所有节点都找到根 while (any(need_update)) { # 将当前root_id替换为它对应父节点的id DF_in[need_update, root_id := DF_in[match(root_id, id), parent_id]] # 更新标记:只有当前root_id还有上级父节点的才需要继续溯源 need_update <- need_update & !is.na(DF_in[match(DF_in$root_id, id), parent_id]) } # 3. 按需求将本身是根节点的记录的root_id设为NA DF_in[is.na(parent_id), root_id := NA] # 查看结果 print(DF_in)
运行结果验证
运行后得到的DF_in和你给出的预期DF_out结构完全一致:
id parent_id root_id 1: 1 NA NA 2: 2 NA NA 3: 3 1 1 4: 4 2 2 5: 5 3 1 6: 6 4 2 7: 7 1 1 8: 8 2 2 9: 9 3 1 10: 10 4 2
方案优势
- 性能优异:data.table的操作均为向量化实现,即使是十万级以上的层级数据也能快速处理
- 稳定性高:不会出现递归层级过深导致的栈溢出问题
- 逻辑简单易维护,不需要额外依赖其他包
内容的提问来源于stack exchange,提问作者ahnungslos
相关产品推荐
相关产品推荐

