You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Python NetworkX本体子图转换为RDF格式并导入Protégé

问题描述

我需要在Python中加载本体图,根据指定的目标节点列表筛选所有前驱节点生成子图,并将该子图保存为可导入Protégé软件的RDF格式(.obo或.owl)。目前我通过以下代码加载本体数据库:

url = "http://purl.obolibrary.org/obo/hp.obo"
graph = obonet.read_obo(url)

已成功生成子图,代码如下:

df_nodes = pd.read_csv('./code_test.csv', header = None)
nodes = list(df_nodes[0])

def predecessor_nodes(node):
    node_list.append(node)
    pred = graph.predecessors(node)
    for node2 in pred:
        return predecessor_nodes(node2)

node_list = []
for node in nodes:
    predecessor_nodes(node)
node_set = set(node_list)
node_list = list(node_set)

result = graph.subgraph(node_list)

但无法找到将子图保存为RDF格式的方法,请问是否可行?若不可行,能否直接在原格式下完成上述操作?

解决方案

先修正前驱节点遍历的bug

你的predecessor_nodes函数存在逻辑问题:遇到第一个前驱节点就直接return,会遗漏同一层级的其他前驱节点。正确的递归遍历方式应该是:

def predecessor_nodes(node):
    if node not in node_list:
        node_list.append(node)
        # 遍历所有前驱节点,递归收集
        for pred_node in graph.predecessors(node):
            predecessor_nodes(pred_node)

这样能确保所有层级的前驱节点都被完整收集。


保存为可导入Protégé的格式

方案1:直接保存为OBO格式

obonet没有内置的子图导出API,但可以手动按照OBO格式规范生成内容,生成的文件可直接导入Protégé:

def save_subgraph_to_obo(subgraph, output_path):
    with open(output_path, 'w', encoding='utf-8') as f:
        # 写入OBO头部信息
        f.write("format-version: 1.2\n")
        f.write("date: 2024-05-20T12:00:00Z\n")
        f.write("ontology: hp-subset\n")
        f.write("default-namespace: hp\n\n")
        
        # 遍历子图节点,写入Term块
        for node_id, node_data in subgraph.nodes(data=True):
            f.write("[Term]\n")
            f.write(f"id: {node_id}\n")
            # 写入节点名称
            if 'name' in node_data:
                f.write(f"name: {node_data['name']}\n")
            # 写入节点定义(如果有)
            if 'def' in node_data:
                f.write(f"def: {node_data['def']}\n")
            # 写入父节点关系
            for parent_id in subgraph.predecessors(node_id):
                f.write(f"is_a: {parent_id}\n")
            # 空行分隔不同Term
            f.write("\n")

# 调用函数保存子图
save_subgraph_to_obo(result, './hp_subset.obo')

方案2:转换并保存为OWL(RDF)格式

如果需要标准RDF格式的OWL文件,可以借助rdflib库实现:

  1. 将obonet图转换为RDF图
import rdflib

rdf_graph = rdflib.Graph()
# 定义常用的RDF/OWL术语
rdfs_subclassof = rdflib.URIRef("http://www.w3.org/2000/01/rdf-schema#subClassOf")
rdfs_label = rdflib.RDFS.label
iao_def = rdflib.URIRef("http://purl.obolibrary.org/obo/IAO_0000115")

# 遍历obonet图的边和节点,构建RDF三元组
for u, v, key, data in graph.edges(data=True, keys=True):
    if key == 'is_a':
        rdf_graph.add((rdflib.URIRef(u), rdfs_subclassof, rdflib.URIRef(v)))

# 添加节点属性(名称、定义等)
for node_id, node_data in graph.nodes(data=True):
    node_uri = rdflib.URIRef(node_id)
    if 'name' in node_data:
        rdf_graph.add((node_uri, rdfs_label, rdflib.Literal(node_data['name'])))
    if 'def' in node_data:
        rdf_graph.add((node_uri, iao_def, rdflib.Literal(node_data['def'])))
  1. 筛选子图对应的RDF三元组
# 生成子图节点的URI集合
sub_node_uris = {rdflib.URIRef(node_id) for node_id in node_list}
# 筛选包含子图节点的三元组
sub_rdf_graph = rdflib.Graph()
for triple in rdf_graph:
    if triple[0] in sub_node_uris or triple[2] in sub_node_uris:
        sub_rdf_graph.add(triple)
  1. 保存为OWL格式
# 以RDF/XML格式保存,Protégé支持该格式
sub_rdf_graph.serialize(destination='./hp_subset.owl', format='xml')

补充说明

  • OBO和OWL格式都能被Protégé完美识别,OBO更贴近原始本体的结构,OWL是标准RDF语义网格式,可根据需求选择。
  • 如果你的本体包含更多属性(如同义词、注释等),需要在保存函数中对应添加这些属性的写入逻辑。

内容的提问来源于stack exchange,提问作者Alexandre Girard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 16:44:57