如何用Tidyverse或Base R高效获取主题数据的最顶层祖先ID?
高效获取Rebrickable主题的顶层祖先ID方法
Rebrickable的主题数据集包含主题ID、名称及父主题ID,存在多层递归层级(主题可能有祖父、曾祖父等)。示例数据如下:
themes <- data.frame(theme_id = c(206, 207, 208), theme_name = c("Seasonal", "Advent", "City"), parent_theme_id = c(NA, 206, 207))
你已实现了逐行循环的Base R代码来追溯每个主题的顶层祖先ID,以下是更优雅的无逐行循环实现方案:
Tidyverse 方案
借助purrr的递归映射函数结合dplyr,批量生成顶层祖先列:
library(tidyverse) # 定义递归函数,追溯到顶层祖先ID get_top_ancestor <- function(id, df) { parent <- df$parent_theme_id[df$theme_id == id] if (is.na(parent)) { return(id) } else { get_top_ancestor(parent, df) } } # 为数据框添加顶层祖先列 themes <- themes %>% mutate(ancestor_theme_id = map_dbl(theme_id, get_top_ancestor, df = themes))
Base R 优化方案
用lapply/sapply结合递归函数,替代显式逐行循环:
# 定义递归函数 get_top_ancestor_base <- function(id, df) { parent <- df$parent_theme_id[df$theme_id == id] if (is.na(parent)) id else get_top_ancestor_base(parent, df) } # 生成顶层ID向量并添加到数据框 themes$ancestor_theme_id <- sapply(themes$theme_id, get_top_ancestor_base, df = themes)
大规模数据集优化方案
如果数据集包含大量主题,可借助igraph通过图论方法快速获取根节点:
library(igraph) # 将主题关系转为有向图 g <- graph_from_data_frame(themes[, c("theme_id", "parent_theme_id")], directed = TRUE) # 提取每个节点的顶层祖先 themes$ancestor_theme_id <- map_dbl(themes$theme_id, ~ subcomponent(g, ._, mode = "in") %>% names() %>% as.numeric() %>% .[is.na(themes$parent_theme_id[themes$theme_id == .])])
内容的提问来源于stack exchange,提问作者qwr
相关产品推荐
相关产品推荐

