基于继承关系对R语言本体DataFrame进行自定义排序的技术咨询
解决方案:按自定义顶层顺序+继承关系排序本体DataFrame
针对你这个本体DataFrame的排序需求,我整理了一套完整的R代码方案,完全满足你说的**条件B(继承关系优先)>条件A(自定义顶层顺序)**的要求,咱们一步步来实现:
1. 准备基础数据与自定义顺序
首先先把你的原始DataFrame定义好,同时明确需要的顶层实体(直接继承自disease的节点)的自定义顺序:
# 原始本体DataFrame onto <- data.frame( entity = c('disease', 'neurologic disease', 'heart disease', 'lung disease', 'kidney disease', 'gastrointestinal disease', 'seizure', 'iatrogenic seizure', 'cardiomyopathy', 'hypertrophic cardiomyopathy', 'restrictive cardiomyopathy', 'kidney stone', 'glomerulonephritis', 'proliferative gn', 'nonproliferative gn', 'rpgn', 'vasculitic rpgn', 'good pasture', 'wegeners', 'diarrhea', 'asthma', 'pneumonia'), superclass = c('owl:thing', 'disease', 'disease', 'disease', 'disease', 'disease', 'neurologic disease', 'seizure', 'heart disease', 'cardiomyopathy', 'cardiomyopathy', 'kidney disease', 'kidney disease', 'glomerulonephritis', 'glomerulonephritis', 'proliferative gn', 'rpgn', 'rpgn', 'vasculitic rpgn', 'gastrointestinal disease', 'lung disease', 'lung disease'), stringsAsFactors = FALSE # 避免字符转因子的坑 ) # 自定义的顶层实体顺序(直接属于disease的子节点) custom_top_order <- c('neurologic disease', 'heart disease', 'kidney disease', 'lung disease', 'gastrointestinal disease')
2. 构建父-子映射关系
为了方便按继承关系遍历,咱们先把每个父类对应的子类整理成一个映射列表:
# 按superclass分组,提取每个父类对应的所有子entity parent_child_map <- split(onto$entity, onto$superclass)
这个parent_child_map里,每个键是父类实体,对应的值是所有直接继承它的子实体列表,后续递归遍历会用到。
3. 编写递归遍历函数(核心逻辑)
因为本体是树形结构,咱们用递归函数实现父节点在前,所有子节点紧随其后的排序逻辑(条件B的核心):
# 递归函数:给定父节点,返回该节点及其所有子节点的排序列表 traverse_ontology <- function(parent_node) { # 先加入当前父节点 result <- parent_node # 如果当前节点有子节点,递归遍历每个子节点并追加到结果中 if (!is.null(parent_child_map[[parent_node]])) { for (child in parent_child_map[[parent_node]]) { result <- c(result, traverse_ontology(child)) } } return(result) }
4. 生成完整排序后的实体列表
先处理根节点disease,再按自定义顺序遍历它的子节点,把每个子节点的完整子树都追加进去:
# 先加入根节点disease,再按自定义顺序遍历顶层实体的子树 sorted_entities <- c('disease') for (top_entity in custom_top_order) { sorted_entities <- c(sorted_entities, traverse_ontology(top_entity)) }
这样既保证了顶层顺序符合你的要求,又严格遵循了子节点紧跟父节点的继承规则。
5. 对原DataFrame进行排序
最后用生成的sorted_entities重新排列原DataFrame:
# 按排序后的实体列表重新整理DataFrame sorted_onto <- onto[match(sorted_entities, onto$entity), ] # 查看最终结果 print(sorted_onto)
验证结果
运行后你会得到完全符合需求的排序:
- 根节点
disease在最前面 - 顶层实体严格按你自定义的顺序排列
- 每个实体的所有子节点都会紧跟在父节点之后,完全遵循继承层级
补充说明
- 后续如果需要调整顶层顺序,只需要修改
custom_top_order向量即可,非常灵活 - 方案完全满足条件B优先级高于条件A的要求:只要是子节点,一定会紧跟父节点,不受字母顺序影响;只有同一层级的顶层节点才会使用自定义顺序
内容的提问来源于stack exchange,提问作者ayeh
相关产品推荐
相关产品推荐

